Laravel 5:强制使用 csrf 验证 [GET] 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31606926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 5: force to validate [GET] requests using csrf
提问by mwafi
by default Laravel 5 validate & match "tokens" for all [POST] requests, how to tell L5 to validate "GET, PUT & Delete" requests too?
默认情况下,Laravel 5 验证并匹配所有 [POST] 请求的“令牌”,如何告诉 L5 也验证“GET、PUT 和删除”请求?
-> prevent any request without valid token
-> 阻止任何没有有效令牌的请求
thanks,
谢谢,
采纳答案by Romain Lanz
Laravel validate the token for POST, PUT and DELETE. You don't need to validate the token for a GET request if you follow a RESTful system.
Laravel 验证 POST、PUT 和 DELETE 的令牌。如果您遵循 RESTful 系统,则不需要验证 GET 请求的令牌。
From the documentation:
从文档:
You do not need to manually verify the CSRF token on POST, PUT, or DELETE requests. The VerifyCsrfToken HTTP middleware will verify token in the request input matches the token stored in the session.
您无需在 POST、PUT 或 DELETE 请求上手动验证 CSRF 令牌。VerifyCsrfToken HTTP 中间件将验证请求输入中的令牌是否与会话中存储的令牌匹配。
回答by Ziki
You can create your own middleware that will take care of it and replace the default Laravel VerifyCsrfToken class. In Laravel 5.3:
您可以创建自己的中间件来处理它并替换默认的 Laravel VerifyCsrfToken 类。在 Laravel 5.3 中:
Create your new middleware
php artisan make:middleware VerifyCsrfTokenAll
Replace the middleware class in
app/Http/Kernel.php
- search forprotected $middlewareGroups
and replaceVerifyCsrfToken::class
by your new middleware. So it can look like this:protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfTokenAll::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ...
In
app/Http/Middleware/VerifyCsrfTokenAll.php
make it extend original verifier and just override theisReading()
method as this one is responsible for bypassing the GET requests. Something like this depending on your use case:<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfTokenAll extends BaseVerifier { /** * Determine if the HTTP request uses a ‘read' verb. * * @param \Illuminate\Http\Request $request * @return bool */ protected function isReading($request) { return false; // return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']); } }
创建新的中间件
php artisan make:middleware VerifyCsrfTokenAll
替换中间件类
app/Http/Kernel.php
- 搜索protected $middlewareGroups
并替换VerifyCsrfToken::class
为您的新中间件。所以它看起来像这样:protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfTokenAll::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ...
在
app/Http/Middleware/VerifyCsrfTokenAll.php
使其延长原有验证,只是重写isReading()
方法,因为这是一个负责绕过GET请求。像这样的事情取决于您的用例:<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfTokenAll extends BaseVerifier { /** * Determine if the HTTP request uses a ‘read' verb. * * @param \Illuminate\Http\Request $request * @return bool */ protected function isReading($request) { return false; // return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']); } }
If you only wanted to validate in on certain routes, it is better to do it as a route middleware as in my case - I created a VerifyCsrfTokenGet
middleware and assigned it in app/Http/Kernel
to $routeMiddleware
group like this:
如果您只想在某些路由上进行验证,最好将其作为路由中间件来执行,就像我的情况一样 - 我创建了一个VerifyCsrfTokenGet
中间件并将其分配app/Http/Kernel
到这样的$routeMiddleware
组中:
protected $routeMiddleware = [
'csrf_get' => \App\Http\Middleware\VerifyCsrfTokenGet::class,
...
In app/Http/MIddleware/VerifyCsrfTokenGet.php
I did the verification:
在app/Http/MIddleware/VerifyCsrfTokenGet.php
我做了验证:
public function handle($request, Closure $next)
{
// check matching token from GET
$sessionToken = $request->session()->token();
$token = $request->input('_token');
if (! is_string($sessionToken) || ! is_string($token) || !hash_equals($sessionToken, $token) ) {
throw new \Exception('CSRF token mismatch exception');
}
return $next($request);
}
and finally assigned this to any route as a csrf_middleware
whereever I want to validate it, eg. in constructor of some of the controllers:
最后将其分配给任何路线作为csrf_middleware
我想验证它的任何地方,例如。在一些控制器的构造函数中:
class InvoicesController extends Controller
{
function __construct()
{
// define middleware
$this->middleware('csrf_get', ['only' => ['pay', 'createmail']]);
}
回答by connor
"csrf token" is just an ordinary session value with a key name "_token" ,you can just get and reset this value directly. like this:
"csrf token" 只是一个普通的会话值,键名为 "_token" ,你可以直接获取和重置这个值。像这样:
$token = $this->request->get('_token');
if(is_null($token) || $token!=csrf_token())
throw new AppException('illegal_pay_operation');
else
Session::regenerateToken();