目录
1.php 的 CSRF 保护机制的代码演示如下(面向过程演示,现在的 php 开发,几乎不会使用面向过程开发,而是面向对象):
2.因此,Ajax 向后端发出请求时,Ajax 方法体的数据输入要带上 CSRF 保护标志,否则后端不会响应:
二、jQuery 的 Ajax 不要用下面的写法,原因就是,在 403、404 或者 505 的情况下不会有提示,在调试或者用户体验上都很麻烦。
四、一个函数体包含 Ajax 的函数体时,Ajax 内 return 的数据不会直接返回给函数体,也就是函数体获取不到 Ajax 返回的数据,用下面的方法才能正确获取,Ajax 必须使用同步请求!
一、Ajax 请求的 CSRF 保护机制
开发普通页面,在一般情况下,我们使用 jquery 的 Ajax 代替原生 js 向后端发起请求是很方便的。后端在一般情况下,我们使用的是像 laravel、Yii、ThankPHP 或者 CodeIgniter 等等这样的框架。这些框架无一例外都使用了 CSRF 保护机制,什么是 CSRF?CSRF 跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性。简单理解一下,最常见的情况,就是 A 站点的页面去请求 B 站点的 RestFul 接口请求,所以 CSRF 保护机制非常重要。因此 Ajax 向后端请求时遇到最大的坑,就是忘了要带上 CSRF 标志,而后端认为这是在跨站点请求。下面是以 jQuery 的 Ajax 为例。
1.php 的 CSRF 保护机制的代码演示如下(面向过程演示,现在的 php 开发,几乎不会使用面向过程开发,而是面向对象):
1)前端页面 index.php:
<?php
/**
* 前端页面
*/
session_start();
//生成随机字符串
function randomStr($max = 16){
$str = 'abcdefghijklmnopqrstuvwxyz'.
'0123456789'.
'ABCDEFJHIJKLMNOPQRSTUVWXYZ';
$val = '';
$str = str_shuffle($str); //打乱字符串
for($i = 0; $i < $max; $i++){
$val .= $str[rand(0, strlen($str) - 1)];
}
return $val;
}
$_SESSION['token'] = randomStr();
//此函数给URL重写机制添加名/值对。
//此函数要写在 html 页面前端中;如果是 MVC 模式,应包含在 view 视图文件内
output_add_rewrite_var('token', $_SESSION['token']);
include_once 'view.php';
print_r(ob_list_handlers());
2)后端页面 form.php:
<?php
/**
* 后端页面
*/
session_start();
echo '原始的值:'.$_SESSION['token'].'<br>收到的值:'.$_POST['token'].'<br>';
// 服务端判断 token 后执行。
// 处于安全考虑,判断是否相等时应该使用 === 来判断,即类型相等,内容相等。
if(filter_has_var(INPUT_POST, "token") && $_POST['token'] === $_SESSION['token']){
// 这是防 CSRF 后接收到的数据
echo '<strong style="color:red">安全地收到数据了!内容为:'.$_POST['var2'].'</strong><br>';
}
print_r(ob_list_handlers());
3)view 视图页面 view.php:
<div>
<a href="file.php">link</a>
<a href="http://example.com">link2</a>
<form action="form.php" method="post">
<input type="text" name="var2" value="这是默认值!"/>
<input type="submit" value="确定">
</form>
</div>
效果图:
2.因此,Ajax 向后端发出请求时,Ajax 方法体的数据输入要带上 CSRF 保护标志,否则后端不会响应:
$.ajax({
data: {
"<?= csrf_token() ?>": csrf // csrf 保护(CodeIgniter 框架演示)
},
url:"https://url.com/class/function",
success:function(data){
// 成功后的方法体
return true;
},
error:function(x){
// 失败后的方法体,一般像下面这样给出提示即可,一般 403、404 都会成功给出提示。
// swal 是 sweetalert 模态框框架的提示框,相当于 js 的 alert()
swal("提示:", "错误提示:" + x.status + " " + x.statusText + ",请刷新页面重试!", "error");
return false;
}
});