主要内容
问题:
在使用springboot(2.6.13)+springsecurity+thymeleaf练习时,通过AJAX调用控制器的POST请求,将返回的HTML片段插入thymeleaf定义的片段标识,来实现局部刷新效果时,发现AJAX请求报错。
PS:这里引用一下我局部刷新的实现方式
SpringBoot+thymeleaf+ajax实现局部刷新详情
Thymeleaf局部刷新
thmeleaf模板引擎使用总结
原因:
还是springsecurity的问题:“Spring Security 默认启用了 CSRF 保护,这意味着对于非 GET、HEAD、TRACE 或 OPTIONS 请求,Spring Security 会期望在请求中包含一个 CSRF 令牌。这个令牌通常是通过一个隐藏的表单字段或一个 HTTP 头部来传输的。”
处理方式
- 在配置类中直接关闭springsecurity的CSRF 保护;
- 在thymeleaf模板中引入CSRF令牌变量,在AJAX中获取到变量值,调用接口时传递,下面看代码。
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
//其他内容.....
//头部定义好CSRF参数,这个是thymeleaf与springsecurity约定的参数名称
//不要更改
<meta name="_csrf" th:content="${_csrf.token}" />
<meta name="_csrf_header" th:content="${_csrf.headerName}" />
</head>
<body>
<div id="pagedlist">
//具体页面,有一个按钮next来触发ajax...
</div>
//js内部,调用AJAX时,使用这两个参数
//假设我请求下一页
<script type="text/javascript">
//事件监听
$("#pagedlist").on("click", "#next",function () {
//获取CSRF
var csrfToken =
$('meta[name="_csrf"]').attr("content");
var csrfHeader =
$('meta[name="_csrf_header"]').attr("content");
$.ajax({
url: "/user/list",
type: "post",
//加上下面的beforeSend的方法还是回调我也不清楚
beforeSend: function(xhr) {
xhr.setRequestHeader(csrfHeader, csrfToken);
},
//下面正常请求
data: {
pageNum: 2,
pageSize: 10
},
success: function (data) {
$("#pagedlist").html(data);
}
})
});
</script>
</body>
</html>