Laravel CSRF 令牌

Posted

技术标签:

【中文标题】Laravel CSRF 令牌【英文标题】:Laravel CSRF Token 【发布时间】:2014-05-17 14:41:45 【问题描述】:

编辑:我应该在一开始就这么说,我在 FronEnd 中使用 AngularJS,我通过 XHR 发出所有请求。 我正在为每个用户请求使用CSRF Token 开发一个应用程序。

我应该在每次请求后重新生成Token 吗?

有点像

Session::forget("_token") and Session::put("_token", RANDOM_SOMETHING)

或者每个用户使用同一个Session就足够了吗?

有什么好处吗?

【问题讨论】:

你使用令牌做什么?假设您将它用于防止 XSS 以外的其他用途,很难说它对于您的场景是否足够“好” @itachi Laravel 的 CSRF 令牌用于防止跨站点请求(通常是 XSS)。它是保存到网站会话中的令牌,并在每次提交表单时发送,因此必须从带有会话的网站提交表单才能获得正确的会话......而不是使用跨站点脚本伪造请求。 @Sam 是的。但是 CSRF 和 XSS 是两个非常不同的方面。拥有令牌会在 csrf 中帮助您,但在 xss 中没有。 @itachi 很公平,感谢您指出这一点。我的解释很不标准,但是(在我看来)这一点仍然存在,我们需要知道 OP 使用 CSRF 令牌来保护他的应用程序的意图。 【参考方案1】:

如果你想在控制器中获取 CSRF Token,那么你可以像这样使用它并重定向 post Route

$CSRFToken = csrf_token();

简单易学 希望对你有帮助

【讨论】:

【参考方案2】:

CSRF 令牌通过将 cookie 令牌与 服务器令牌。

你可以在 laravel 中通过 csrf_token() 辅助函数生成 csrf 令牌。如果你想要完整的 csrf 字段,那么你可以使用csrf_field() 函数和 csrf 内部逻辑是

function csrf_field()

   return new htmlString('<input type="hidden" name="_token" value="'.csrf_token().'">');

当新请求将产生时,laravel 每次都会创建随机令牌,并在存储后存储在浏览器 cookie 和 session 中它的相互比较就像cookie == session token

Laravel 内部逻辑如下,你可以在VerifyCsrfToken Middleware 中找到它。

/**
 * Determine if the session and input CSRF tokens match.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function tokensMatch($request)

    $token = $this->getTokenFromRequest($request);

    return is_string($request->session()->token()) &&
           is_string($token) &&
           hash_equals($request->session()->token(), $token);


/**
 * Get the CSRF token from the request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return string
 */
protected function getTokenFromRequest($request)

    $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');

    if (! $token && $header = $request->header('X-XSRF-TOKEN')) 
        $token = $this->encrypter->decrypt($header);
    

    return $token;


/**
 * Add the CSRF token to the response cookies.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Symfony\Component\HttpFoundation\Response  $response
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function addCookieToResponse($request, $response)

    $config = config('session');

    $response->headers->setCookie(
        new Cookie(
            'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
            $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
        )
    );

    return $response;

【讨论】:

很好的例子,谢谢【参考方案3】:

如果您使用 Laravel 5.6,请在表单顶部执行以下操作以创建 CSRF 令牌的隐藏输入字段

  @csrf

【讨论】:

【参考方案4】:

在 Laravel 5 中使用 Blades 模板,这非常简单。

如果你只想要csrf token的值,可以这样写:

 csrf_token() 

生成令牌值如下:

7YC0Sxth7AYe4RFSjzaPf2ygLCecJhPbyXhz6vvF

如果您使用的是表单,可以在表单内添加以下代码行:

 csrf_field() 

会生成这样的html:

<input type="hidden" name="_token" value="7YC0Sxth7AYe4RFSjzaPf2ygLCecJhblahblah">

【讨论】:

【参考方案5】:

视情况而定。如果攻击者不是 MITM,从某种意义上说,他们无法窃听您的 Web 应用程序和 API 服务器之间的流量,那么整个会话的单个 CSRF 令牌就足够了。

假设您也在服务器端保护敏感操作(即只允许资源所有者访问资源,例如“删除我的帐户”等),令牌将确保发出请求的浏览器是合法的、经过身份验证的用户的浏览器。我想这就是你应该担心的全部。

另一方面,如果攻击者能够查看 Web 应用程序和您的 API 之间的非安全流量,他们可能会获取 CSRF 令牌和您的 session_id 并透明地做坏事。在这种情况下,为每个请求(POST,或任何执行敏感操作的类型)授予、使用和随后丢弃令牌只会使他们的工作变得更加困难,但你仍然注定要失败。

我的 2 美分...

【讨论】:

OP 应该接受这个答案,因为它是唯一真正尝试回答他的问题的答案。 @hlev 你说的很对。那你有什么建议? @r89human 和以前一样。 TLS (HTTPS) 和用户会话的单个令牌对于大多数用途来说应该足够了。有关更全面的概述,请参阅 OWASP 备忘单。 cheatsheetseries.owasp.org/cheatsheets/…【参考方案6】:

Laravel 应该为你做这件事,你不需要管理 _token 的创建/删除

<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

请参阅此处文档中的“CSRF 保护”部分:http://laravel.com/docs/security

【讨论】:

我在 FronEnd 中使用 AngularJS,我在每个 XHR 请求上发送 CSRF 令牌,我没有以常规方式处理它 我尝试使用 Session::token() 和其他方法来检索令牌,但 Laravel 不会重新生成令牌,我的问题是我应该重新生成令牌还是简单地使用相同的令牌在整个会话中

以上是关于Laravel CSRF 令牌的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 CSRF 令牌发布到 Laravel API?

如何在 Laravel 中禁用 CSRF 令牌以及为啥我们必须禁用它?

在 laravel 5.5 的验证 csrf 令牌中没有收到错误令牌不匹配异常

Laravel 4.2 根据请求频率生成新的 CSRF 令牌?

Laravel:使用 Varnish 和 CSRF 令牌

为啥 Laravel 4 CSRF 令牌不起作用?