laravel报错:TokenMismatchException in VerifyCsrfToken.php
2017-11-17 16:58
716 查看
这个错误是刚学习Laravel的时候碰到的,只是当时还没开始写博客,一直也没记录下来,今天下午又碰到了这个问题,趁着这会儿没啥事,赶紧总结下。
Laravel自动为每个用户Session生成了一个CSRF Token,该Token可用于验证登录用户和发起请求者是否是同一人,如果不是则请求失败。Laravel提供了一个全局帮助函数csrf_token(本地存放在D:\www\laravel5.1\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php)来获取该Token值。
从我们程序员的角度来看的话,请参考下面这个链接:
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
这段代码的意思是在提交表单的时候,会自动带上laravel生成的csrf_token()的值,然后在访问路由的时候,laravel会判断这个值,失败则报错:TokenMismatchException,成功则正常访问路由。
2、如果进行ajax的post请求的时候并没有提交form,表单,此时我们可以通过在meta中写入一些属性来金星csrf防护。
在ajax中,我们需要加上header属性:
这样,我们就可以正确的访问路由了。
以上两种方法我都试了一下,绝对是没问题的,可以有效的避免错误。
1、找到csrf的中间件,然后可以按照我下面的代码来修改
当使用CSRF的时候,选用上面的代码。当禁用的时候,选用下面的代码。
2、有的时候我们既需要开启CSRF防护,又需要在一些特性的post请求时不带csrf_token(),怎么办?
答:laravel框架为我们提供了一个特殊的属性,如下所示:
这段代码的意思是利用except来进行路由过滤。在我们except中的是我们不想被防护的路由名称。此处的’upload’和’rsa_post’,都是我需要post方式访问的路由。大家可以自己试一下,经过测试,这种方式是完全没问题的。
由中间件中的代码可知,laravel是通过中间件的handle()方法进行防护的。有IDE的同学可以直接追踪下该函数。没有用IDE编辑器的同学可以通过一定的路径来访问源码。
路径:laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCrsfToken.php
源码如下:
这里大家可以根据源码中的几个方法来了解laravel的防护机制
2、源码分析:
1)首先Laravel开启Session时会生成一个token值并存放在Session中(Illuminate\Session\Store.php第90行start方法),对应源码如下:
2)然后重点分析VerifyToken中间件的handle方法,该方法中先通过isReading方法判断请求方式,如果请求方法是HEAD、GET、OPTIONS其中一种,则不做CSRF验证;
3)再通过shouldPassThrough方法判断请求路由是否在$excpet属性数组中进行了排除,如果做了排除也不做验证;
4)关于这个runningUnitTests()方法,我也不太明白这个是干嘛的。后来通过百度,大致知道了这个函数是为了检测laravel项目的运行环境的。如果是’cli’启动的话,则正常。
5)最后通过tokensMatch方法判断请求参数中的CSRF TOKEN值和Session中的Token值是否相等,如果相等则通过验证,否则抛出TokenMismatchException异常。
对应源码如下:
以上都是laravel关于CSRF防护的内容。果然不懂的时候看源码才是王道啊。
end
一、为什么报这个错误
答:这是由于laravel框架自带的csrf_token防护中间件的原因。这个中间件的位置在/app/middleware/VrifyCsrfToken.php。这个中间件的作用就是为了过滤Post请求。Laravel自动为每个用户Session生成了一个CSRF Token,该Token可用于验证登录用户和发起请求者是否是同一人,如果不是则请求失败。Laravel提供了一个全局帮助函数csrf_token(本地存放在D:\www\laravel5.1\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php)来获取该Token值。
二、什么是csrf防护
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。从我们程序员的角度来看的话,请参考下面这个链接:
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
三、如果避免这个错误。
1、在post方式提交表单的时候,加上laravel自带的全局帮助函数csrf_token。<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
这段代码的意思是在提交表单的时候,会自动带上laravel生成的csrf_token()的值,然后在访问路由的时候,laravel会判断这个值,失败则报错:TokenMismatchException,成功则正常访问路由。
2、如果进行ajax的post请求的时候并没有提交form,表单,此时我们可以通过在meta中写入一些属性来金星csrf防护。
<head> 4000 <title>Laravel</title> <meta name="csrf-token" content="{{ csrf_token() }}"> </head>
在ajax中,我们需要加上header属性:
$.ajax({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, url: "{{url('/rsa_post')}}", type: "post", dataType: "json",
这样,我们就可以正确的访问路由了。
以上两种方法我都试了一下,绝对是没问题的,可以有效的避免错误。
四、当我们不想启用框架自带的csrf防护的时候
进入:laravel/app/Middleware/VerifyCsrfToken.php1、找到csrf的中间件,然后可以按照我下面的代码来修改
public function handle($request, Closure $next) { // 使用CSRF return parent::handle($request, $next); // 禁用CSRF //return $next($request); }
当使用CSRF的时候,选用上面的代码。当禁用的时候,选用下面的代码。
2、有的时候我们既需要开启CSRF防护,又需要在一些特性的post请求时不带csrf_token(),怎么办?
答:laravel框架为我们提供了一个特殊的属性,如下所示:
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
//
'upload',
'rsa_post',
];
/* public function handle($request, Closure $next) { // 使用CSRF return parent::handle($request, $next); // 禁用CSRF //return $next($request); }*/
}
这段代码的意思是利用except来进行路由过滤。在我们except中的是我们不想被防护的路由名称。此处的’upload’和’rsa_post’,都是我需要post方式访问的路由。大家可以自己试一下,经过测试,这种方式是完全没问题的。
五、laravel实现CSRF防护的源代码解析。
1、源代码位置:由中间件中的代码可知,laravel是通过中间件的handle()方法进行防护的。有IDE的同学可以直接追踪下该函数。没有用IDE编辑器的同学可以通过一定的路径来访问源码。
路径:laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCrsfToken.php
源码如下:
public function handle($request, Closure $next) { if ( $this->isReading($request) || $this->runningUnitTests() || $this->shouldPassThrough($request) || $this->tokensMatch($request) ) { return $this->addCookieToResponse($request, $next($request)); } throw new TokenMismatchException; }
这里大家可以根据源码中的几个方法来了解laravel的防护机制
2、源码分析:
1)首先Laravel开启Session时会生成一个token值并存放在Session中(Illuminate\Session\Store.php第90行start方法),对应源码如下:
public function start() { // 读取session $this->loadSession(); if (! $this->has('_token')) { $this->regenerateToken(); } return $this->started = true; }
2)然后重点分析VerifyToken中间件的handle方法,该方法中先通过isReading方法判断请求方式,如果请求方法是HEAD、GET、OPTIONS其中一种,则不做CSRF验证;
3)再通过shouldPassThrough方法判断请求路由是否在$excpet属性数组中进行了排除,如果做了排除也不做验证;
4)关于这个runningUnitTests()方法,我也不太明白这个是干嘛的。后来通过百度,大致知道了这个函数是为了检测laravel项目的运行环境的。如果是’cli’启动的话,则正常。
5)最后通过tokensMatch方法判断请求参数中的CSRF TOKEN值和Session中的Token值是否相等,如果相等则通过验证,否则抛出TokenMismatchException异常。
对应源码如下:
public function handle($request, Closure $next) { if ($this->isReading($request) || $this->shouldPassThrough($request) || $this->tokensMatch($request)) { return $this->addCookieToResponse($request, $next($request)); } throw new TokenMismatchException; }
以上都是laravel关于CSRF防护的内容。果然不懂的时候看源码才是王道啊。
end
相关文章推荐
- laravel post TokenMismatchException in VerifyCsrfToken.php line 53 问题解决方法
- laravel post TokenMismatchException in VerifyCsrfToken.php line 53 问题解决方法
- TokenMismatchException in VerifyCsrfToken.php line
- TokenMismatchException Laravel
- Laravel 出现"RuntimeException inEncrypter.php line 43: The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths."问题的解决办法
- Laravel数据模型层M错误MassAssignmentException in Model.php line 407: username
- [PHP] - Laravel - CSRF token禁用方法
- laravel 5异常错误:FatalErrorException in Handler.php line 38的解决
- Laravel : InvalidArgumentException in Carbon.php line 425: Data missing
- [PHP] - Laravel - CSRF token禁用方法与排除验证csrf_token的url设置
- Laravel NotFoundHttpException in RoutesRequests.php line 442
- 解决Laravel 5上传大文件时出现TokenMismatchException的问题
- Laravel学习之VerifyCsrfToken 报错解决方法详解
- [PHP] - Laravel - CSRF token禁用方法
- [PHP] - Laravel - CSRF token禁用方法
- Laravel - CSRF token禁用方法
- Laravel - CSRF token禁用方法
- Exception in thread "main" java.util.InputMismatchException
- 日常Exception(一):java.lang.VerifyError: Inconsistent stackmap frames at branch target 1209 in method..
- spring security 4.2后出现CouldnotverifytheprovidedCSRFtokenbecauseyoursessionwasnotfound