[ Laravel 5.8 文档 ] 基础组件 —— CSRF 保护

栏目: PHP · 发布时间: 5年前

内容简介:跨站请求伪造(CSRF)是一种通过伪装授权用户的请求来攻击授信网站的恶意漏洞。Laravel 通过自带的 CSRF 保护中间件让避免应用遭到跨站请求伪造攻击变得简单:Laravel 会自动为每一个被应用管理的有效用户会话生成一个 CSRF “令牌”,然后将该令牌存放在 Session 中,该令牌用于验证授权用户和发起请求者是否是同一个人。

[ Laravel 5.8 文档 ] 基础组件 —— CSRF 保护

简介

跨站请求伪造(CSRF)是一种通过伪装授权用户的请求来攻击授信网站的恶意漏洞。

Laravel 通过自带的 CSRF 保护中间件让避免应用遭到跨站请求伪造攻击变得简单:Laravel 会自动为每一个被应用管理的有效用户会话生成一个 CSRF “令牌”,然后将该令牌存放在 Session 中,该令牌用于验证授权用户和发起请求者是否是同一个人。

任何时候在 Laravel 应用中定义 HTML 表单,都需要在表单中引入 CSRF 令牌字段,这样 CSRF 保护中间件才能够对请求进行验证。要想生成包含 CSRF 令牌的隐藏输入字段,可以使用 Blade 指令 @csrf

<form method="POST" action="/profile">
    @csrf
    ...
</form>

中间件组 web 中的中间件 VerifyCsrfToken 会自动为我们验证请求输入的 token 值和 Session 中存储的 token 是否一致,如果没有传递该字段或者传递过来的字段值和 Session 中存储的数值不一致,则会抛出异常。

为了演示该功能,我们在 routes/web.php 中定义一组测试路由:

Route::get('form_without_csrf_token', function (){
    return '<form method="POST" action="/hello_from_form"><button type="submit">提交</button></form>';
});

Route::get('form_with_csrf_token', function () {
    return '<form method="POST" action="/hello_from_form">' . csrf_field() . '<button type="submit">提交</button></form>';
});

Route::get('hello_from_form', function (){
   return 'hello laravel!';
});

我们在浏览器中访问 http://blog.test/form_without_csrf_token 并点击页面上的提交按钮时,页面报错,抛出 MethodNotAllowedHttpException 异常,出现这个异常往往就是意味着没有传递 CSRF 令牌字段或者传递的令牌字段不正确:

[ Laravel 5.8 文档 ] 基础组件 —— CSRF 保护

而当我们访问 http://blog.test/form_csrf_token 并点击页面上的提交按钮时,页面显示正常。

注:CSRF 中间件只只作用于 routes/web.php 中定义的路由,因为该文件下的路由分配了 web 中间件组,而 VerifyCsrfToken 位于 web 中间件组中。

CSRF 令牌 & JavaScript

构建 JavaScript 驱动的应用时,为方便起见,可以让 JavaScript HTTP 库自动在每个请求中添加 CSRF 令牌。默认情况下, resources/js/bootstrap.js 文件会将 csrf-token meta 标签值注册到 Axios HTTP 库。如果你没有使用这个库,则需要手动在应用中配置该实现。

排除指定 URL 不做 CSRF 安全校验

有时候我们需要从 CSRF 保护中间件中排除一些 URL,例如,如果你使用了第三方支付系统(如支付宝或微信支付)来处理支付并用到他们提供的回调功能,这时候就需要从 Laravel 的 CSRF 保护中间件中排除回调处理器路由,因为第三方支付系统并不知道要传什么 token 值给我们定义的路由。

通常我们需要将这种类型的路由放到文件 routes/web.php 之外,比如 routes/api.php 。不过,如果必须要加到 routes/web.php 中的话,你也可以在 VerifyCsrfToken 中间件中将要排除的 URL 添加到 $except 属性数组:

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
     * 从 CSRF 验证中排除的 URL
     *
     * @var array
     */
    protected $except = [
        'alipay/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ];
}

注:运行测试时 CSRF 中间件会自动禁止。

X-CSRF-Token

除了将 CSRF 令牌作为 POST 参数进行验证外,还可以通过设置 X-CSRF-Token 请求头来实现验证, VerifyCsrfToken 中间件会检查 X-CSRF-TOKEN 请求头。实现方式如下,首先创建一个 meta 标签并将令牌保存到该 meta 标签:

<meta name="csrf-token" content="{{ csrf_token() }}">

然后在 js 库(如 jQuery)中添加该令牌到所有请求头,这为基于 AJAX 的请求提供了简单、方便的方式来避免 CSRF 攻击:

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

注:默认情况下, resources/js/bootstrap.js 文件会将 csrf-token meta 标签值添加到 Axios HTTP 库,如果你没有使用这个库,则需要手动配置应用的行为。

X-XSRF-Token

Laravel 还会将 CSRF 令牌保存到名为 XSRF-TOKEN 的 Cookie 中,你可以使用该 Cookie 值来设置 X-XSRF-TOKEN 请求头。

一些 JavaScript 框架,比如 Angular 和 Axios,会为你自动进行上述设置,基本上你不太需要手动设置这个值。

最后, VerifyCsrfToken 中间件框架底层实现源码位于 vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php ,感兴趣的同学可以去一窥究竟。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Master Switch

The Master Switch

Tim Wu / Knopf / 2010-11-2 / USD 27.95

In this age of an open Internet, it is easy to forget that every American information industry, beginning with the telephone, has eventually been taken captive by some ruthless monopoly or cartel. Wit......一起来看看 《The Master Switch》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具