Java 如何将csrf令牌添加到html表单中?

Java 如何将csrf令牌添加到html表单中?,java,spring,spring-boot,spring-security,csrf,Java,Spring,Spring Boot,Spring Security,Csrf,在我的应用程序中启用csrf(删除行.csrf().disable())后,我的登录请求停止工作-/loginPOST将我重定向到主页: 请求如下所示: 在页面上,我有以下js: <script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script> ... $('#login-form').submit(function (ev) { ev.preventDefault();

在我的应用程序中启用csrf(删除行
.csrf().disable()
)后,我的登录请求停止工作-
/login
POST
将我重定向到主页:

请求如下所示:

在页面上,我有以下js:

<script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>
...
$('#login-form').submit(function (ev) {
    ev.preventDefault(); // to stop the form from submitting
    var headerName = "X-CSRF-TOKEN";
    var token = Cookies.get('XSRF-TOKEN')
    $('<input>').attr('type', 'hidden').attr('name', '_csrf').attr('value', Cookies.get('XSRF-TOKEN')).appendTo('#login-form');
    this.submit(); // If all the validations succeeded
    })
build.gradle:
尝试直接将此输入添加到表单中(不使用jQuery):


如果您需要将
CsrfToken
持久化到cookie中,默认情况下,
CookieSrfTokenRepository
将写入名为
XSRF-TOKEN
的cookie,并从名为
X-XSRF-TOKEN
的头或HTTP参数
\u csrf

读取它。我尝试了不同的方法,最终找到了解决方案:

以前的
index.html
位于文件夹
/resources/static

我把它放在文件夹
/resources/templates
中。此外,我还添加了依赖项:

compile('org.thymeleaf:thymeleaf-spring5');
并明确声明控制器:

@RequestMapping("/")
public String index(){
   return "index";
} 
index.html
如下所示:

<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<html lang="en" ng-app="springChat" xmlns:th="http://www.springframework.org/schema/beans">
<head>
    ...
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <meta name="_csrf_parameter_name" th:content="${_csrf.parameterName}"/>

....
</body>     
<script type="application/javascript">

    $('#login-form').submit(function (ev) {
        ev.preventDefault(); // to stop the form from submitting
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameter_name']").attr("content");
        $('<input>').attr('type', 'hidden').attr('name', paramName).attr('value', token).appendTo('#login-form');

        this.submit(); 
    });
</script>
</html>

...
....
$(“#登录表单”).submit(函数(ev){
ev.preventDefault();//停止表单提交
var token=$(“meta[name=''u csrf']”)attr(“content”);
var paramName=$(“meta[name=”\u csrf\u parameter\u name'])attr(“content”);
$('').attr('type','hidden').attr('name',paramName.).attr('value',token.).appendTo('#login form');
这个。提交();
});

如果我们没有显式声明映射,并且没有尝试将
th:content=“${u csrf.token}”
之类的值插入变量,那么看起来像是spring启动在
/resources/static
原始html中搜索

我使用原始html,所以我不能使用它。这个解决方案有效,但您知道为什么在jsp表单中,我们可以发送表单数据,但在使用Ajax时,我们需要将其添加为标题,而不是正文中的表单数据吗?好的,我可以看到你添加了更多信息。我想请您添加更多关于您得到的错误的详细信息(或者您期望的行为,但不是这样)。您使用服务器模板语言JSP还是Thymeleaf?@holmis83我使用rawhtml@john结果相同)/登录响应302,而不是成功登录。如果我显式禁用csrf(.csrf().disable())登录成功,谢谢!为了引起大家的注意,th:在这里是非常重要的前缀。
$(function () {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");

    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
    });
});
compile('org.thymeleaf:thymeleaf-spring5');
@RequestMapping("/")
public String index(){
   return "index";
} 
<html lang="en" ng-app="springChat" xmlns:th="http://www.springframework.org/schema/beans">
<head>
    ...
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <meta name="_csrf_parameter_name" th:content="${_csrf.parameterName}"/>

....
</body>     
<script type="application/javascript">

    $('#login-form').submit(function (ev) {
        ev.preventDefault(); // to stop the form from submitting
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameter_name']").attr("content");
        $('<input>').attr('type', 'hidden').attr('name', paramName).attr('value', token).appendTo('#login-form');

        this.submit(); 
    });
</script>
</html>