【laravel】Disabling CSRF for Specific Routes - Laravel 5

本文详细介绍了如何在Laravel5中为特定路由禁用CSRF保护,通过创建并使用自定义中间件,以排除某些路由不受CSRF令牌验证的影响,适合处理第三方API回调等场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文 http://www.camroncade.com/disable-csrf-for-specific-routes-laravel-5/

Disabling CSRF for Specific Routes - Laravel 5

Update: If you are working on Laravel 5.1, there is support for this right out of the box: See this post for more information

I've been working with Laravel 5 lately, and it's great. But with a new version comes new defaults. CSRF protection for instance, is now always active with the implementation of Middleware, where in Laravel 4, it was something you "turned-on" as you needed it. In my opinion, this is a great move for Laravel, making it more secure out-of-the-box.

However, there may come a time when you want to exclude specific routes and requests from worrying about looking for a CSRF token. (In my case, I had a POST route that was used exclusively as a callback for a third-party API. It uses a different form of authentication that service renders CSRF not only unnecessary, but a hinderence. This is what I did to "disable" CSRF for specic routes.

Middleware

Laravel 5 comes with middleware. It replaces L4's filters and while they are fundamentally different, for the purpose of this guide, you can pretty much treat them as such. (For a more in-depth look at Middleware, check out Laravel 5.0 - Middleware (Filter-style))

If you're not intimately familiar with middleware, that's okay. This is also going to serve as a mini-intro to working with middleware.

How Laravel 5 Handles CSRF

In laravel 5, there is a middleware class, Illuminate\Foundation\Http\Middleware\VerifyCsrfToken with a method handle($request, Closure $closure) that is exceuted every request. It is here that it either lets the request continue on to the controller, or it throws a TokenMismatchException. We want to alter this process so that it skips CSRF protection for routes of our choosing.

Take a look at the included VerifyCsrfToken class. You can find it in the foldervendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/. The only public function is handle($request, Closure $next) and it looks like this: 

public function handle($request, Closure $next) { if ($this->isReading($request) || $this->tokensMatch($request)) { return $this->addCookieToResponse($request, $next($request)); } throw new TokenMismatchException; }

You can see that unless $this->isReading($request) OR $this->tokensMatch($request) return true, a TokenMismatchException is thrown. Otherwise, the request coninues normally. Take a look at what each of these methods do.

The isReading() method just checks for "reading" verbs: HEAD, GET, OPTIONS. If one of these is being used, it skips over the CSRF check.

Remember, CSRF is meant to prevent other websites from submitting POST data to yours, so we don't worry about it for GET requests.

 

The tokensMatch($request) closure is called if isReading($request) returns false. This does the work of actually deciding whether a token was included in the request, and if so, checks whether or not it matches the one stored in the session.

What we are going to do

Okay. Time to work. We are going to add a third condition in that if statment, called $this->excludedRoutes($request). But we don't want to modify the class we've been looking at. That clas is managed by composer and would get overwritten.

Because we are using namespaces, we don't have to worry about it being the same name as the one we are extending.We are going to create a new class that *extends* the VerifyCsrfToken class. I'm going to put mine in `App/Http/Middleware` and I'm going to name it `VerifyCsrfMiddleware.php`. The class, blank and extending VerifyCsrfToken looks like this: 

<?php namespace App\Http\Middleware; class VerifyCsrfToken extends \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken { }

Because we extended the Laravel default middleware class, we have access to all of it's public and protected methods. Yes, that includes `tokensMatch($request)` and `isReading($request)`. When a middleware class is called, Laravel looks for the the `handle($request, Closue $closure)` method, so we need to create that. We also want to just add an additional `OR` condition to the existing `handle($request, Closure $closure)` in the class we are extending. So go ahead and copy that into *your* blank middleware class, and let's add a `$this->excludedRoutes($request)` method that is called as the third condition. Mine now looks like this. 

public function handle($request, Closure $next) { if ($this->isReading($request) || $this->excludedRoutes($request) || $this->tokensMatch($request)) { return $this->addCookieToResponse($request, $next($request)); } throw new TokenMismatchException; }

Notice that I added `excludedRoutes($request)` as the second condition. This is because we don't need to call `$this->tokensMatch($request)` if `excludedRoutes($request)` returns true.As pointed out in the comments, copying the handle class does go against DRY. Check the comments for a cleaner alternative.

Now we just need to create the tokensMatch($request) method. I wanted an array that I could add my route-exceptions to, so this is what I came up with: 

protected function excludedRoutes($request) { $routes = [ 'some/route/path', 'users/non-protected-route' ]; foreach($routes as $route) if ($request->is($route)) return true; return false; }

This way, if I ever need to exclude a route from CSRF, I can just add it to the array here.

Telling Laravel about our new middleware class

Looks good! We've got one last step before we're done though. We need to tell Laravel to use our new VerifyCsrfToken class in place of the included one. This is done in the App/Http/Kernal.php file. Go ahead and make the change to:

'App\Http\Middleware\VerifyCsrfToken'

And that's it you're done!

Closing thoughts

There are a few things to keep in mind. One, you need to be very careful anytime you do disable CSRF protection, and whether or not you actually have to disable it. Many times there is a way to include the CSRF token in the request, and if it's possible, you should probably do it. Always be careful and make sure you do have extra protections if this is what you are doing.

This is by no means the only way, nor can I imagine it being the best way, to accomplish this. If you see ways to improve this, or if you have a cleaner way of ignoring CSRF for specific routes, I'm always open to better ways of doing things and I'd love to hear about it.

转载于:https://www.cnblogs.com/china-flint/p/9685480.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值