laravel CSRF 保护

在开始之前让我们来实现上述表单访问伪造的完整示例,为简单起见,我们在路由闭包中实现所有业务代码:

Route::get(‘task/{id}/delete‘, function ($id) {
    return ‘<form method="post" action="‘ . route(‘task.delete‘, [$id]) . ‘">
                <input type="hidden" name="_method" value="DELETE">
                <button type="submit">删除任务</button>
            </form>‘;
});

Route::delete(‘task/{id}‘, function ($id) {
    return ‘Delete Task ‘ . $id;
})->name(‘task.delete‘);

在 http://blog.test/task/1/delete 点击「删除任务」按钮提交表单,会显示 419 异常页面:

初学者可能会困惑,这是什么原因呢?

不得不说,Laravel 5.7 引入的错误提示页面虽然好看,但是错误提示信息太少,这其实是因为默认情况下,为了安全考虑,Laravel 期望所有路由都是「只读」操作的(对应请求方式是 GET、HEAD、OPTIONS),如果路由执行的是「写入」操作(对应请求方式是 POST、PUT、PATCH、DELETE),则需要传入一个隐藏的 Token 字段(_token)以避免[跨站请求伪造攻击](CSRF)。在我们上面的示例中,请求方式是 DELETE,但是并没有传递 _token 字段,所以会出现异常。

注:跨站请求伪造是一种通过伪装授权用户的请求来攻击授信网站的恶意漏洞,关于跨站请求伪造攻击可以参考维基百科了解明细:https://zh.wikipedia.org/wiki/%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0

避免跨站请求伪造攻击的措施就是对写入操作采用非 GET 方式请求,同时在请求数据中添加校验 Token 字段,Laravel 也是这么做的,这个 Token 值会在渲染表单页面时通过 Session 生成,然后传入页面,在每次提交表单时带上这个 Token 值即可实现安全写入,因为第三方站点是不可能拿到这个 Token 值的,所以由第三方站点提交的请求会被拒绝,从而避免 CSRF 攻击。

在 Laravel 中,和表单方法伪造一样,支持通过 HTML 表单隐藏字段传递这个值:

Route::get(‘task/{id}/delete‘, function ($id) {
    return ‘<form method="post" action="‘ . route(‘task.delete‘, [$id]) . ‘">
                <input type="hidden" name="_method" value="DELETE">
                <input type="hidden" name="_token" value="‘ . csrf_token() . ‘">
                <button type="submit">删除任务</button>
            </form>‘;
});

这样我们再次访问 http://blog.test/task/1/delete 页面点击「删除任务」按钮,即可成功提交表单。

当然,如果你是在 JavaScript 脚本中执行 HTTP 请求,也可以很方便的传递这个 Token 值执行写入操作,首先需要在 HTML <head> 标签内新增一个 <meta> 元素来存储 Token 值:

<meta name="csrf-token" content="<?php echo csrf_token(); ?>" id="csrf-token">

然后我们在 JavaScript 脚本中将这个 Token 值放到一个全局请求头设置中,以便每个 HTTP 请求都会带上这个头信息,避免每次发起请求都要添加这个字段。如果你使用的是 jQuery 的话,可以这么做:

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

如果你使用的是 Vue 的话,可以这么做:

Vue.http.interceptors.push((request, next) => {
    request.headers[‘X-CSRF-TOKEN‘] = document.querySelector(‘#csrf-token‘).getAttribute(‘content‘);
    next();
});

Laravel 会在每次请求都检查请求头中是否包含 X-CSRF-TOKEN,并检查其值是否和 Session 中的 Token 值是否一致。

注:如果你使用了 Laravel 自带的 assets/js/bootstrap.js, 则上述 Vue 请求头设置不需要自己编写,因为 bootstrap.js 中已经包含了这个逻辑。

原文地址:https://www.cnblogs.com/sgm4231/p/10283512.html

时间: 2024-10-24 09:06:33

laravel CSRF 保护的相关文章

laravel csrf保护

有时候我们的项目需要和外部的项目进行接口对接,如果是post的方式请求;laravel要求csrf保护 但是别人是ci框架或者没有csrf_token的;该如何处理呢? 可以把我们不需要csrf的url加入到白名单中 学习来源: http://laravelacademy.org/post/6742.html 然后一般模拟接口请求的时候,可以用firefox的RESTClient来模拟 如果是post请求的话 在正文中 直接写 id=1&&name=hhh 还需要一个header头:Con

HTTP层 —— CSRF保护

简介 跨站请求伪造是一种通过伪装授权用户的请求来利用授信网站的恶意漏洞.Laravel 使得防止应用遭到跨站请求伪造攻击变得简单. Laravel 自动为每一个被应用管理的有效用户会话生成一个 CSRF "令牌",该令牌用于验证授权用户和发起请求者是否是同一个人. 任何时候在 Laravel 应用中定义HTML表单,都需要在表单中引入CSRF令牌字段,这样CSRF保护中间件才能够正常验证请求.想要生成包含 CSRF 令牌的隐藏输入字段,可以使用辅助函数 csrf_field 来实现:

laravel5.2总结--csrf保护

CSRF攻击: CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作.我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的.所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求. Laravel 会自动生成一个 CSRF token 给每个用户的 Session.该 t

如何模拟登陆添加了CSRF保护的网站

上次写了篇文章,内容是如何利用WebClient模拟登陆CSRF控制的网站,回复中有人还是不理解,现在另开一篇,打算说说用Python如何来登陆. 开写之前,先说下为什么webrequest不行,常规情况下,我们在利用webrequest的时候,都是如下的形式: 1 string url = "loginurl"; 2 StringBuilder sb = new StringBuilder(); 3 sb.Append("username=un"); 4 sb.A

[PHP] - Laravel - CSRF token禁用方法

前文 CSRF攻击和漏洞的参考文章: http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html Laravel默认是开启了CSRF功能,需要关闭此功能有两种方法: 方法一 打开文件:app\Http\Kernel.php 把这行注释掉: 'App\Http\Middleware\VerifyCsrfToken' 方法二 打开文件:app\Http\Middleware\VerifyCsrfToken.php 修改为: <?php n

Laravel5.0 CSRFチェックを無効化(修改后可以像5.1以上那样从CSRF保护中排除指定URL)

Laravel5では全てのPOSTに勝手にCSRFチェックが付いてきます.便利と言えば便利ですが.Laravel外からのPOSTを受け取りたいときなど大迷惑です. CSRFチェックを排除する方法が何故かなかなか見当たらなかったので調査結果を記載. Kernel デフォルトで適用されるミドルウェアはapp/Http/Kernel.phpに記載されています.'App\Http\Middleware\VerifyCsrfToken'が書かれている行を削除するとCSRFチェックが無効化されます. この場

Django 的 CSRF 保护机制(转)

add by zhj:其实我个人推荐前端不要将数据放在cookie中,而是放在其它本地存储(HTML5中称之为Web Storage),本地存储与cookie的一 个重要区别在于:本地数据不会自动加在http请求中.这样也就不会有CSRF了.假设用户登录了网站A,而在网站B中有一个CSRF攻击标签,点 击这个标签就会访问网站A,如果前端数据(包括sessionid)都放在本地存储的话,当在网站B点击CSRF攻击标签时,标签绑定的方法是无法获 取网站A本地存储中的sessionid的,这样用户在服

Django 的 CSRF 保护机制

用 django 有多久,我跟 csrf 这个概念打交道就有久了. 每次初始化一个项目时都能看到 django.middleware.csrf.CsrfViewMiddleware 这个中间件 每次在模板里写 form 时都知道要加一个 {% csrf_token %} tag 每次发 ajax POST 请求,都需要加一个 X_CSRFTOKEN 的 header 但是一直我都是知其然而不知其所以然,没有把 csrf 的机制弄清楚.昨天稍微研究了一下,总结如下. 什么是 CSRF CSRF,

3、登陆表单提交CSRF及验证码

1.表单提交,并将其提交到本页 (1) form 属性method为post方法,修改路由,使其接收post.get的请求 Route::any('/admin/login','Admin\[email protected]'); (2)LoginController.php 修改login方法,根据不同的请求返回不同的内容 如果请求方法为get ,返回登陆页面:如果请求为post,就行验证 use Illuminate\Support\Facades\Input; public functio