Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security CSRF Token not working with AJAX call & form submit in same JSP

I am trying to implement spring security (ver 3.2.3) CSRF token in my project by referring below links

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'.

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

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

<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 &lt input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /&gt statement in form tag 

Thanks & Regards, Siva

like image 994
siva Avatar asked Nov 28 '22 03:11

siva


2 Answers

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.

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:

var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");

Pass the CSRF token as a header:

$.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.

The reference is here:

http://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html#csrf-include-csrf-token-ajax

Hope this helps.

like image 184
anykey_dev Avatar answered Dec 06 '22 17:12

anykey_dev


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:

url: './getMerchantByInstitution.htm',
headers: headers,    // THIS WAS ADDED
data: data,//"institutionId=" + option,
dataType:'json',

Let me know if this works.

like image 20
Aeseir Avatar answered Dec 06 '22 16:12

Aeseir