laravel的csrf token 的了解及使用

之前在项目中因为没有弄清楚csrf token的使用,导致发请求的话,一直请求失败,今天就一起来看一下csrf的一些东西。

 1.Cross-site request forgery 跨站请求伪造,也被称为 “one click attack” 或者 session riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。CSRF 则通过伪装来自受信任用户的请求来利用受信任的网站。

2.从字面意思就可以理解:当你访问 fuck.com 黑客页面的时候,页面上放了一个按钮或者一个表单,URL/action 为 http://you.com/delete-myself,这样引导或迫使甚至伪造用户触发按钮或表单。在浏览器发出 GET 或 POST 请求的时候,它会带上 you.com 的 cookie,如果网站没有做 CSRF 防御措施,那么这次请求在 you.com 看来会是完全合法的,这样就会对 you.com 的数据产生破坏。

3.第三方恶意网站也是可以构造post请求并提交至被攻击网站的,所以POST方式提交只是提高了攻击的门槛而已,无法防范CSRF攻击,所以对post也要进行防范

关于csrf更多的请参考 https://segmentfault.com/q/1010000000713614  https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/

在laravel中为了防止csrf 攻击,设计了  csrf token

laravel默认是开启了csrf token 验证的,关闭这个功能的方法:

(1)打开文件:app\Http\Kernel.php

  把这行注释掉:‘App\Http\Middleware\VerifyCsrfToken’

(2)打开文件 app\Http\Middleware\VerifyCsrfToken.php

    修改handle方法为:   

1  public function handle($request, Closure $next)
2     {
3         // 使用CSRF
4         //return parent::handle($request, $next);
5         // 禁用CSRF
6         return $next($request);
7     }

csrf的使用:

(1)在html的代码中加入:

1 <input type="hidden" name="_token" value="{{ csrf_token() }}" />

(2)使用cookie 方式 ,将app\Http\Middleware\VerifyCsrfToken.php修改为:

 1 <?php namespace App\Http\Middleware;
 2 
 3 use Closure;
 4 use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
 5 
 6 class VerifyCsrfToken extends BaseVerifier {
 7 
 8     /**
 9      * Handle an incoming request.
10      *
11      * @param  \Illuminate\Http\Request  $request
12      * @param  \Closure  $next
13      * @return mixed
14      */
15     public function handle($request, Closure $next)
16     {
17         return parent::addCookieToResponse($request, $next($request));
18     }
19 
20 }

使用cookie方法就不用在每个页面都加入这个input 的 hidden 标签

还可以部分使用csrf检测部分不使用。

注:本文从laravel的csrf token开始到此参考:http://blog.csdn.net/proud2005/article/details/49995389

关于  laravel 的 csrf 保护更多的内容请参考 laravel学院文档:http://laravelacademy.org/post/6742.html

下面说说我们那个项目中的关于csrf token的使用:

在我的另一篇文章中也提到了我们那个项目中的使用过程

在中间件VerifyCsrfToken.php中修改内容为:
 1 protected function tokensMatch($request)
 2 {
 3     // If request is an ajax request, then check to see if token matches token provider in
 4     // the header. This way, we can use CSRF protection in ajax requests also.
 5     $token = $request->ajax() ? $request->header('X-CSRF-TOKEN') : $request->input('_token');
 6     return $request->session()->token() == $token;
 7 }
 8 
 9 public function handle($request,\Closure $next){
10     //todo:需要在添加了登录验证之后,取消
11    //这样是在post请求的时候不进行csrf token验证
12     if($request->method() == 'POST')
13     {
14         return $next($request);
15     }
16     
17     return parent::handle($request,$next);
18 }
然后在vue中的bootstrap.js中的引入的axios的位置添加
 1 window.axios.defaults.headers.common = { 2 'X-CSRF-TOKEN': document.querySelector('meta[name="X-CSRF-TOKEN"]').content, 3 'X-Requested-With': 'XMLHttpRequest' 4 }; 

在index.blade.php中添加
 1 <meta name="X-CSRF-TOKEN" content="{{csrf_token()}}"> 

上面的代码都好理解,就是获取到 csrf_token令牌,然后提交,再经过中间件验证即可

下面重点来说一下 VerifyCsrfToken.php中间件

中间件的内容最开始应该只有一个 handle函数:这个是所有的都进行csrf token验证

1  public function handle($request,\Closure $next){
2         return parent::handle($request,$next);
3     }

现在项目中的这个中间件的内容

 1 <?php
 2 
 3 namespace App\Http\Middleware;
 4 
 5 use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
 6 
 7 class VerifyCsrfToken extends BaseVerifier
 8 {
 9     /**
10      * The URIs that should be excluded from CSRF verification.
11      *
12      * @var array
13      */
14     protected $except = [
15         //
16     ];
17 //    protected $except = [
18 //
19 //        '/classroom_upload',
20 //        'wk_upload',
21 //        'wechat',
22 //    ];
23     protected function tokensMatch($request)
24     {
25         // If request is an ajax request, then check to see if token matches token provider in
26         // the header. This way, we can use CSRF protection in ajax requests also.
27         $token = $request->ajax() ? $request->header('X-CSRF-TOKEN') : $request->input('_token');
28         return $request->session()->token() == $token;
29     }
30 
31 
32     public function handle($request,\Closure $next){
33         //todo:需要在添加了登录验证之后,取消
34         if($request->method() == 'POST')
35         {
36             return $next($request);
37         }
38         
39         return parent::handle($request,$next);
40     }
41 }

我们来看一下 VerifyCsrfToken.php的源码             Illuminate\Foundation\Http\Middleware\VerifyCsrfToken.php;

  1 <?php
  2 
  3 namespace Illuminate\Foundation\Http\Middleware;
  4 
  5 use Closure;
  6 use Carbon\Carbon;
  7 use Illuminate\Foundation\Application;
  8 use Symfony\Component\HttpFoundation\Cookie;
  9 use Illuminate\Contracts\Encryption\Encrypter;
 10 use Illuminate\Session\TokenMismatchException;
 11 
 12 class VerifyCsrfToken
 13 {
 14     /**
 15      * The application instance.
 16      *
 17      * @var \Illuminate\Foundation\Application
 18      */
 19     protected $app;
 20 
 21     /**
 22      * The encrypter implementation.
 23      *
 24      * @var \Illuminate\Contracts\Encryption\Encrypter
 25      */
 26     protected $encrypter;
 27 
 28     /**
 29      * The URIs that should be excluded from CSRF verification.
 30      *
 31      * @var array
 32      */
 33     protected $except = [];
 34 
 35     /**
 36      * Create a new middleware instance.
 37      *
 38      * @param  \Illuminate\Foundation\Application  $app
 39      * @param  \Illuminate\Contracts\Encryption\Encrypter  $encrypter
 40      * @return void
 41      */
 42     public function __construct(Application $app, Encrypter $encrypter)
 43     {
 44         $this->app = $app;
 45         $this->encrypter = $encrypter;
 46     }
 47 
 48     /**
 49      * Handle an incoming request.
 50      *
 51      * @param  \Illuminate\Http\Request  $request
 52      * @param  \Closure  $next
 53      * @return mixed
 54      *
 55      * @throws \Illuminate\Session\TokenMismatchException
 56      */
 57     public function handle($request, Closure $next)
 58     {
 59         if (
 60             $this->isReading($request) ||
 61             $this->runningUnitTests() ||
 62             $this->inExceptArray($request) ||
 63             $this->tokensMatch($request)
 64         ) {
 65             return $this->addCookieToResponse($request, $next($request));
 66         }
 67 
 68         throw new TokenMismatchException;
 69     }
 70 
 71     /**
 72      * Determine if the HTTP request uses a ‘read’ verb.
 73      *
 74      * @param  \Illuminate\Http\Request  $request
 75      * @return bool
 76      */
 77     protected function isReading($request)
 78     {
 79         return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']);
 80     }
 81 
 82     /**
 83      * Determine if the application is running unit tests.
 84      *
 85      * @return bool
 86      */
 87     protected function runningUnitTests()
 88     {
 89         return $this->app->runningInConsole() && $this->app->runningUnitTests();
 90     }
 91 
 92     /**
 93      * Determine if the request has a URI that should pass through CSRF verification.
 94      *
 95      * @param  \Illuminate\Http\Request  $request
 96      * @return bool
 97      */
 98     protected function inExceptArray($request)
 99     {
100         foreach ($this->except as $except) {
101             if ($except !== '/') {
102                 $except = trim($except, '/');
103             }
104 
105             if ($request->is($except)) {
106                 return true;
107             }
108         }
109 
110         return false;
111     }
112 
113     /**
114      * Determine if the session and input CSRF tokens match.
115      *
116      * @param  \Illuminate\Http\Request  $request
117      * @return bool
118      */
119     protected function tokensMatch($request)
120     {
121         $token = $this->getTokenFromRequest($request);
122 
123         return is_string($request->session()->token()) &&
124                is_string($token) &&
125                hash_equals($request->session()->token(), $token);
126     }
127 
128     /**
129      * Get the CSRF token from the request.
130      *
131      * @param  \Illuminate\Http\Request  $request
132      * @return string
133      */
134     protected function getTokenFromRequest($request)
135     {
136         $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
137 
138         if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
139             $token = $this->encrypter->decrypt($header);
140         }
141 
142         return $token;
143     }
144 
145     /**
146      * Add the CSRF token to the response cookies.
147      *
148      * @param  \Illuminate\Http\Request  $request
149      * @param  \Symfony\Component\HttpFoundation\Response  $response
150      * @return \Symfony\Component\HttpFoundation\Response
151      */
152     protected function addCookieToResponse($request, $response)
153     {
154         $config = config('session');
155 
156         $response->headers->setCookie(
157             new Cookie(
158                 'XSRF-TOKEN', $request->session()->token(), Carbon::now()->getTimestamp() + 60 * $config['lifetime'],
159                 $config['path'], $config['domain'], $config['secure'], false
160             )
161         );
162 
163         return $response;
164     }
165 }

其中app下面的VerifyCsrfToken中间件是继承源码中的那个VerifyCsrfToken类

我们项目中重写了tokensMatch方法,然后调父类的handle的时候,父类中使用的是this调用tokensMatch的,个人感觉应该最后有用的是我们重写的这个方法,如果是ajax请求的话,我们就检测$request->header('X-CSRF-TOKEN')与session中的token是否一样 否则的话,就检测 $request->input('_token')与session中的token是否一样。

本人对laravel的原理还不太了解,上面的内容如果有什么错误的话,欢迎指教。

如需转载请注明:

本文出处:http://www.cnblogs.com/zhuchenglin/p/7723997.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏解Bug之路

从linux源码看socket的close

笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情。上篇博客讲了socket的阻塞和非阻塞,这篇就开始谈一谈socket的...

26670
来自专栏散尽浮华

Nginx/Apache服务连接数梳理

统计连接数,使用netstat命令或ss命令都可以 1)统计连接数(80端口) [root@wang ~]# netstat -nat|grep -i "80"...

21880
来自专栏Jerry的SAP技术分享

ABAP Netweaver, Hybris Commerce和SAP 云平台的登录认证

在事务码SICF里选择一个服务,在明细页面对Procedure字段点击F1,查看Logon Procedure的帮助文档。

20030
来自专栏FreeBuf

MOTS攻击之TCP攻击

1. 概述 继续进行MOTS类型攻击方式的进展。这里再次强调一下,MOTS 是指 Man-On-The-Side,是一种在旁路监听模式下的攻击方式;和 MITM...

39650
来自专栏coding

RabbitMQ实战4.发布与订阅交换机临时队列发布与订阅功能实现执行结果流程总结参考文档

RabbitMQ并非直接将消息投递到队列中,而是要经过交换机,交换机再与队列绑定。那么,什么是交换机? 如何通过交换机与队列的绑定实现发布与订阅功能?

10920
来自专栏耕耘实录

tcpdump使用小记

版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

11930
来自专栏FreeBuf

利用PRET控制远程打印机测试

Pret是用来对打印机安全进行测试的工具。它通过网络或者USB连接到设备,并利用给定打印机的语言进行渗透。目前绝大多数的打印机都是使用PostScript,pj...

19530
来自专栏玄魂工作室

Python灰帽编程 3.1 ARP欺骗

ARP欺骗是一种在局域网中常用的攻击手段,目的是让局域网中指定的(或全部)的目标机器的数据包都通过攻击者主机进行转发,是实现中间人攻击的常用手段,从而实现数据监...

44060
来自专栏landv

烽火2640路由器命令行手册-04-网络协议配置命令

配置静态ARP映射,静态ARP映射会永久保留在ARP缓存中。如果要删除配置的静态ARP映射的话,使用 no arp 命令。

13820
来自专栏信安之路

浅谈ddos的测试方式

DOS(denial of service--拒绝服务)攻击的目的是使服务正常功能不可用。不像其他类型的攻击的目的是获取敏感信息,Dos攻击是不会威胁到敏感信息...

27300

扫码关注云+社区

领取腾讯云代金券