Laravel中实现csrf的Ajax请求
一、CSRF是什么?
Laravel 可以轻松地保护你的应用程序免受 「cross-site request forgery」(CSRF)攻击,跨站点请求伪造是一种恶意攻击,它凭借已通过身份验证的用户身份来运行未经过授权的命令。
Laravel 会自动为每个活跃用户的会话生成一个 CSRF 「令牌」。该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。
二.CSRF可以做什么?
这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。《详细内容可以访问该链接查看》
三、分析
我们先从一个简单的例子来看一下csrf到底是何神圣?
首先我们先web.php中配置路由
# csrf验证路由
Route::get('/csrf', function () {
return "this is csrf get";
});
Route::post('/csrf', function () {
return "this is csrf post";
});
打开Postman工具,进行路由测试
get返回的结果:,执行成功
post请求执行效果图,报错419
419分析原因:查看app/Http下的Kernel.php,跨域查到一个 \App\Http\Middleware\VerifyCsrfToken::class, 配置文件,我们进行注释,再次执行post的请求,发现可以执行到post或者在VerifyCsToken中将不需要进行效验的路由放置csrf中间件当中,也可以成功执行。(不推荐这样使用),一般情况我们使用的是在HTML中加一个@csrf。
我们做一个简单的表单测试,提交的路劲就是上述的login地址,请求方式采取post请求,我们不添加@csrf这个,发现提交后报419,添加@csrf后,发现这个可以得到return的值 “用户登录成功”,并且在浏览器上按下F12,可以发现在账号那一行中会有一个value值出现,value中的值就是一个令牌。所以得出一个结论,@csrf是浏览器给的一个令牌,如果使用post请求必须使用csrf,使其生成一个令牌。
<form action="login" method="post">
{{-- 添加令牌 --}}
@csrf
账号: <input type="text" required name="username"> <br>
密码: <input type="password" required name="password"><br>
<input type="submit" value="submit">
</form>
四、Ajax的使用
使用ajax进行异步请求,这里主要说明几个问题
1、必须先导入jQuery才可以进行下一步
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
2、如果是使用Ajax异步请求,必须使用除了检查 POST 参数中的 CSRF 令牌外, VerifyCsrfToken 中间件还会检查 X-CSRF-TOKEN 请求头。你应该将令牌保存在 HTML meta 标签中。一旦你创建了 meta 标签,就可以指示像 jQuery 这样的库自动将令牌添加到所有请求的头信息中。还可以为基于 AJAX 的应用提供简单、方便的 CSRF 保护。
<meta name="csrf-token" content="{{csrf_token()}}">
3、 headers,这个header需要添加一个s,里面放置的是token的json数据,后面 不需要添加 " ; "
headers:{
'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
},
代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{{-- 引入css --}}
{{-- <link rel="stylesheet" href="{{URL::asset('css/style.css')}}">--}}
<title>Document</title>
</head>
<body>
<form action="login" method="post">
{{-- 添加令牌 --}}
@csrf
账号: <input type="text" required name="username"> <br>
密码: <input type="password" required name="password"><br>
<input type="submit" value="submit">
</form>
</body>
</html>
------------------------ajax实现请求---------------------
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
{{-- 这个csrftoken是用来识别这个csrf的 --}}
<meta name="csrf-token" content="{{csrf_token()}}">
<script>
// 使用立即执行函数
(function () {
$.ajax({
url:'login',
type:'post',
headers:{
// 获取token
'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
},
success:function (msg) {
console.log(msg);
},
error:function () {
console.log(error);
}
});
})
</script>