欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

laravel的csrf防御机制详解

shiping1 的头像
一、什么是CSRF

CSRF是Cross Site Request Forgery的缩写,乍一看和XSS差不多的样子,但是其原理正好相反,XSS是利用合法用户获取其信息,而CSRF是伪造成合法用户发起请求。具体操作原理看google。

二、Laravel的CSRF防御过程

Laravel框架会自动在用户 session 中存放一个随机令牌(token),并且将这个令牌作为一个隐藏字段包含在表单信息中。当然,你也可以使用表单的 token 方法直接调用令牌字段的HTML代码。

1. 在视图页面中:

{{ Form::token() }}

2. 任何地方可以这样获取:

csrf_token();

三、Token产生原理

通过 Illuminate\Session\Store 类的 getToken 方法获取随机产生长度为40的字符串,而这40个字符是由 Illuminate\Support\Str 类的 random 方法产生,但是这个方法有个地方总觉得不太合适。分析如下:

public static function random($length = 16)
  {
    if (function_exists('openssl_random_pseudo_bytes'))
    {
      $bytes = openssl_random_pseudo_bytes($length * 2);

      if ($bytes === false)
      {
        throw new \RuntimeException('Unable to generate random string.');
      }

      return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
    }

    return static::quickRandom($length);
  }

可以看到,这里的一个处理是这样的,如果 openssl_random_pseudo_bytes 这个方法获取随机数据失败的话(在PHP文档关于这个openssl_random_pseudo_bytes方法的介绍中提示在某些情况下可能执行失败,看来还是比较危险的),直接抛出异常了,这时候网站就报错了,各位同学会不会觉得他们这样做太粗鲁了?

我觉得合适的办法是在 openssl_random_pseudo_bytes 这个方法执行返回 false 的情况下继续执行,通过这个函数的静态方法quickRandom获取,代码如下:

public static function random($length = 16)
  {
    if (function_exists('openssl_random_pseudo_bytes'))
    {
      $bytes = openssl_random_pseudo_bytes($length * 2);

      if ($bytes !== false)
      {
        return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
      }

    }

    return static::quickRandom($length);
  }
来自 http://www.tuicool.com/articles/uqa6Jbv
普通分类: