环境

Laravel5.4

什么是CSRF?

维基百科的解释如下:

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。[1] 跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

那是谁利用了“网站对用户网页浏览器的任信”?可能是骇客,也可能是机器人,还可能是没那么友善的用户。

因此,我们有必要做好CSRF的保护。

在Laravel上如何实现CSRF保护?

开启web.php路由中间件的CSRF保护

vi app/Http/Kernel.php

/**

* The application's route middleware groups.

*

* @var array

*/

protected $middlewareGroups = [

'web' => [

\App\Http\Middleware\VerifyCsrfToken::class,

],

];

开启axios自动在ajax请求时发送X-CSRF-TOKEN http header

vi resources/assets/js/bootstrap.js

window.axios.defaults.headers.common['X-CSRF-TOKEN'] = window.Laravel.csrfToken;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

在layout文件(如master.blade.php)或任何需要CSRF保护的blade模板文件设置csrf token

在head处设置meta

在body的script标签里设置window.Laravel.csrfToken

window.Laravel = {

csrfToken: '{{ csrf_token() }}'

};

在body的script标签里设置$.ajaxSetup(为以后要用到的Ajax请求设置默认的值)

$.ajaxSetup({

headers: {

'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')

}

});

在需要直接提交(非ajax提交)的form标签里,设置_token

{{ csrf_field() }}

该模板标签会被blade模板语言编译成,示例:

至此,CSRF保护就设置完成了。

但,我有个疑问,首次打开该网站的页面(GET请求),是没有_token、X-CSRF-TOKEN和X-XSRF-Token的,

而web.php路由中间件CSRF保护会验证所有请求,那岂不是会打不开该页面?而事实上是可以打开的,于是,我找到了如下Laravel源码:

Illuminate\Foundation\Http\Middleware\VerifyCsrfToken:

/**

* Handle an incoming request.

*

* @param \Illuminate\Http\Request $request

* @param \Closure $next

* @return mixed

*

* @throws \Illuminate\Session\TokenMismatchException

*/

public function handle($request, Closure $next)

{

if (

$this->isReading($request) ||

$this->runningUnitTests() ||

$this->inExceptArray($request) ||

$this->tokensMatch($request)

) {

return $this->addCookieToResponse($request, $next($request));

}

throw new TokenMismatchException;

}

/**

* Determine if the HTTP request uses a ‘read’ verb.

*

* @param \Illuminate\Http\Request $request

* @return bool

*/

protected function isReading($request)

{

return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']);

}

/**

* Add the CSRF token to the response cookies.

*

* @param \Illuminate\Http\Request $request

* @param \Symfony\Component\HttpFoundation\Response $response

* @return \Symfony\Component\HttpFoundation\Response

*/

protected function addCookieToResponse($request, $response)

{

$config = config('session');

$response->headers->setCookie(

new Cookie(

'XSRF-TOKEN', $request->session()->token(), Carbon::now()->getTimestamp() + 60 * $config['lifetime'],

$config['path'], $config['domain'], $config['secure'], false

)

);

return $response;

}

意思是,如果请求方式为HEAD、GET和OPTIONS,则发送名为XSRF-TOKEN的cookie,而不作CSRF验证。

完!如果认为有用,可以考虑以赞赏的方式告诉我哦。

参考资料

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐