javascript Spring Security CSRF Token 不适用于 AJAX 调用和表单在同一个 JSP 中提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27182081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security CSRF Token not working with AJAX call & form submit in same JSP
提问by siva
I am trying to implement spring security (ver 3.2.3) CSRF token in my project by referring below links
我正在尝试通过参考以下链接在我的项目中实施 spring 安全(版本 3.2.3)CSRF 令牌
http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#csrfhttp://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag
http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#csrf http://docs.spring.io/autorepo/docs/spring-security/ 4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag
I am able to integrate CSRF token in JSP successfully without AJAX call. But when I tried JSP with AJAX call, getting 'invalid CSRF token exception'. After my analysis I found for both AJAX call & form submission using same token due to this i am getting 'invalid CSRF token exception'.
我能够在没有 AJAX 调用的情况下成功地将 CSRF 令牌集成到 JSP 中。但是当我用 AJAX 调用尝试 JSP 时,得到“无效的 CSRF 令牌异常”。经过我的分析,我发现 AJAX 调用和表单提交都使用相同的令牌,因为我收到了“无效的 CSRF 令牌异常”。
Could please any one help me to get raid of this issue. Is there any way to to generate two tokens i.e. one for AJAX call & one for form submission
请任何人帮助我解决这个问题。有没有办法生成两个令牌,即一个用于 AJAX 调用,一个用于表单提交
security.xml
安全文件
<access-denied-handler ref="accessDenied" />
<intercept-url pattern="/**" access="ROLE_1" />
<form-login default-target-url='/loginUser.htm' always-use-default-target='true' authentication-failure-url='/forms/common/login.jsp?error=true' />
<logout logout-success-url="/forms/common/logout.jsp" invalidate-session="true" delete-cookies="JSESSIONID" />
<session-management invalid-session-url="/forms/common/sessionexpired.jsp" session-authentication-error-url="/forms/common/login.jsp?Error=alreadyLoggedin" >
<concurrency-control expired-url="/forms/common/sessionexpired.jsp" max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
<csrf request-matcher-ref="csrfSecurityRequestMatcher"/>
</http>
<beans:bean class="com.concerto.pg.login.security.CsrfSecurityRequestMatcher" id="csrfSecurityRequestMatcher"/>
JSP
JSP
<head>
<sec:csrfMetaTags />
<script type="text/javascript" charset="utf-8">
function changeList(id,option){
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
var institution = document.getElementById("institutionId").value;
var data = {};
data[csrfParameter] = csrfToken;
data["institutionId"] = option;
if(id=="institutionId"){
var result ='';
$.ajax({
type: "GET",
async: false,
url: './getMerchantByInstitution.htm',
data: data,//"institutionId=" + option,
dataType:'json',
success: function (res) {
result = res;
var htmlVar = '';
for (var i=0; i<result.length; i++){
htmlVar += '<option
value="'+result[i]+'">'+result[i]+'</option>';
}
htmlVar += '<option value="ALL">ALL</option>';
$('#merchantId').html(htmlVar);
}
});
}
}
</script>
</head>
added below < input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> statement in form tag
Thanks & Regards, Siva
感谢和问候, Siva
回答by anykey_dev
To make an AJAX/JSON request with CSRF enabled you have to pass CSRF token as a HTTP Request Header, not a parameter or other data.
要在启用 CSRF 的情况下发出 AJAX/JSON 请求,您必须将 CSRF 令牌作为 HTTP 请求标头传递,而不是参数或其他数据。
On the page, your meta tags should look like these:
在页面上,您的元标记应如下所示:
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
Then, prepare values somewhere in the JS code:
然后,在 JS 代码中的某处准备值:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
Pass the CSRF token as a header:
将 CSRF 令牌作为标头传递:
$.ajax({
type: "GET",
async: false,
url: './getMerchantByInstitution.htm',
data: "institutionId=" + option,
beforeSend: function(xhr) {
// here it is
xhr.setRequestHeader(header, token);
},
success: function(obj) {
// ....
},
....
Though it's totally up to you, I'd recommend to use something like JSON.stringify to pass the data, but it depends, of course.
虽然这完全取决于你,但我建议使用类似 JSON.stringify 的东西来传递数据,但这当然取决于。
The reference is here:
参考资料在这里:
Hope this helps.
希望这可以帮助。
回答by Aeseir
I hope this below answer helps. Make these changes
我希望下面的答案有帮助。进行这些更改
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content"); // THIS WAS ADDED
and after
之后
data[csrfParameter] = csrfToken;
data["institutionId"] = option;
headers[csrfHeader] = csrfToken; // THIS WAS ADDED
finally change in the ajax call:
最后在ajax调用中改变:
url: './getMerchantByInstitution.htm',
headers: headers, // THIS WAS ADDED
data: data,//"institutionId=" + option,
dataType:'json',
Let me know if this works.
让我知道这个是否奏效。
回答by simonalmar
This fixed my issue for me:
这为我解决了我的问题:
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
using org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE
使用 org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE