Laravel 5:强制使用 csrf 验证 [GET] 请求
Laravel 5: force to validate [GET] requests using csrf
默认 Laravel 5 为所有 [POST] 请求验证并匹配 "tokens",如何告诉 L5 也验证 "GET, PUT & Delete" 请求?
-> 阻止任何没有有效令牌的请求
谢谢,
Laravel 验证 POST、PUT 和 DELETE 的令牌。如果您遵循 RESTful 系统,则无需验证 GET 请求的令牌。
来自文档:
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.
您可以创建自己的中间件来处理它并替换默认的 Laravel VerifyCsrfToken class。在 Laravel 5.3:
创建新的中间件php artisan make:middleware VerifyCsrfTokenAll
替换 app/Http/Kernel.php
中的中间件 class - 搜索 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']);
}
}
如果您只想在某些路由上进行验证,最好像我的情况一样将其作为路由中间件来执行 - 我创建了一个 VerifyCsrfTokenGet
中间件并将其分配给 app/Http/Kernel
到$routeMiddleware
这样的群组:
protected $routeMiddleware = [
'csrf_get' => \App\Http\Middleware\VerifyCsrfTokenGet::class,
...
在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);
}
并最终将其作为 csrf_middleware
分配给任何路线,无论我想在哪里验证它,例如。在一些控制器的构造函数中:
class InvoicesController extends Controller
{
function __construct()
{
// define middleware
$this->middleware('csrf_get', ['only' => ['pay', 'createmail']]);
}
"csrf token"只是一个普通的session值,键名是“_token”,你可以直接获取和重置这个值。
像这样:
$token = $this->request->get('_token');
if(is_null($token) || $token!=csrf_token())
throw new AppException('illegal_pay_operation');
else
Session::regenerateToken();
默认 Laravel 5 为所有 [POST] 请求验证并匹配 "tokens",如何告诉 L5 也验证 "GET, PUT & Delete" 请求?
-> 阻止任何没有有效令牌的请求
谢谢,
Laravel 验证 POST、PUT 和 DELETE 的令牌。如果您遵循 RESTful 系统,则无需验证 GET 请求的令牌。
来自文档:
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.
您可以创建自己的中间件来处理它并替换默认的 Laravel VerifyCsrfToken class。在 Laravel 5.3:
创建新的中间件
php artisan make:middleware VerifyCsrfTokenAll
替换
app/Http/Kernel.php
中的中间件 class - 搜索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']); } }
如果您只想在某些路由上进行验证,最好像我的情况一样将其作为路由中间件来执行 - 我创建了一个 VerifyCsrfTokenGet
中间件并将其分配给 app/Http/Kernel
到$routeMiddleware
这样的群组:
protected $routeMiddleware = [
'csrf_get' => \App\Http\Middleware\VerifyCsrfTokenGet::class,
...
在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);
}
并最终将其作为 csrf_middleware
分配给任何路线,无论我想在哪里验证它,例如。在一些控制器的构造函数中:
class InvoicesController extends Controller
{
function __construct()
{
// define middleware
$this->middleware('csrf_get', ['only' => ['pay', 'createmail']]);
}
"csrf token"只是一个普通的session值,键名是“_token”,你可以直接获取和重置这个值。 像这样:
$token = $this->request->get('_token');
if(is_null($token) || $token!=csrf_token())
throw new AppException('illegal_pay_operation');
else
Session::regenerateToken();