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中已经包含了这个逻辑。
laravel CSRF 保护的更多相关文章
- laravel csrf保护
有时候我们的项目需要和外部的项目进行接口对接,如果是post的方式请求;laravel要求csrf保护 但是别人是ci框架或者没有csrf_token的;该如何处理呢? 可以把我们不需要csrf的ur ...
- HTTP层 —— CSRF保护
简介 跨站请求伪造是一种通过伪装授权用户的请求来利用授信网站的恶意漏洞.Laravel 使得防止应用遭到跨站请求伪造攻击变得简单. Laravel 自动为每一个被应用管理的有效用户会话生成一个 CSR ...
- laravel5.2总结--csrf保护
CSRF攻击: CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作.我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 S ...
- Web API CSRF保护实现
Web API CSRF保护实现 这次自己实现了类似jQuery中ajax调用的方法,并且针对RESTFul进行了改造和集成,实现的A2D AJAX接口如下: $.ajax.RESTFulGetCol ...
- Flask-WTF CSRF 保护P3
使用FlaskForm处理请求的任何视图函数都已经获得了CSRF保护.如果有些视图函数还在使用FlaskForm或AJAX请求,请尽快使用FlaskForm提供的CSRF扩展来保护它们. 导入 想要为 ...
- Flask-WTF中的csrf保护
CSRF 保护 这部分文档介绍了 CSRF 保护. 为什么需要 CSRF? Flask-WTF 表单保护你免受 CSRF 威胁,你不需要有任何担心.尽管如此,如果你有不包含表单的视图,那么它们仍需要保 ...
- 如何模拟登陆添加了CSRF保护的网站
上次写了篇文章,内容是如何利用WebClient模拟登陆CSRF控制的网站,回复中有人还是不理解,现在另开一篇,打算说说用Python如何来登陆. 开写之前,先说下为什么webrequest不行,常规 ...
- HTML form without CSRF protection,HTML表单没有CSRF保护
HTML form without CSRF protection =HTML表单没有CSRF保护 CSRF是伪造客户端请求的一种攻击,CSRF的英文全称是Cross Site Request For ...
- [PHP] - Laravel - CSRF token禁用方法
前文 CSRF攻击和漏洞的参考文章: http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html Laravel默认是开启了CSRF功能, ...
随机推荐
- Leetcode#118. Pascal's Triangle(杨辉三角)
题目描述 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例: 输入: 5 输出: [ [1], [1,1], [1,2, ...
- Python 21 Django 实用小案例1
实用案例 验证码与验证 KindEditor 组合搜索的实现 单例模式 beautifulsoup4 验证码与验证 需要安装Pillow模块 pip stall pillow ...
- mysql 架构 ~ MHA 总揽
一 简介:MHA相关二 版本 mha0.56 mha0.57 mha0.58三 切换流程 0 主库已不可达 阶段一 1 从集群选出新主,根据新主同步的binlog信息进行拷贝binl ...
- Javascript - ExtJs - 整合百度文章编辑器
ExtJs - 整合百度文章编辑器(ExtJs UEditor) 第一步:去官网下载最新版本的UEditor,UEditor下载. 第二步:在编辑器根目录创建一个Extjs-Editor.js,录入以 ...
- light oj 1254 - Prison Break 最短路
题目大意:n个点m条边的有向图,q次询问c,s,t,表示汽车邮箱容量为c,求从起点s到终点t的最小费用.汽车在每个点可以加任意的油,每个点的单位油价为a[i]. 题目思路:利用最小费优先队列优化最短路 ...
- c/C++编译的程序占用的内存分为以下几个部分
首先要搞清楚编译程序占用的内存的分区形式:一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等 ...
- tkinter模块常用参数python
1.使用tkinter.Tk()生成主窗口(root = tkinter.Tk()) root.title("标题名") 修改窗体的名字,也可以在创建的时候使用clas ...
- ueditor取消文本编辑器的自动拉伸高度、宽度。
1.首先引入富文本编辑器 <script type="text/javascript" src="<%=basePath%>js/ueditor/ued ...
- Leetcode - 309. Best Time to Buy and Sell Stock with Cooldown
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- 【转】HTTP
[转]HTTP 一.http概述 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTT ...