java - Cross-Origin Resource Sharing with Spring Security -


i'm trying make cors play nicely spring security it's not complying. made changes described in this article , changing line in applicationcontext-security.xml has got post , requests working app (temporarily exposes controller methods, can test cors):

  • before: <intercept-url pattern="/**" access="isauthenticated()" />
  • after: <intercept-url pattern="/**" access="permitall" />

unfortunately following url allows spring security logins through ajax isn't responding: http://localhost:8080/mutopia-server/resources/j_spring_security_check. making ajax request http://localhost:80 http://localhost:8080.

in chrome

when attempting access j_spring_security_check (pending) in chrome options preflight request , ajax call returns http status code 0 , message "error".

in firefox

the preflight succeeds http status code 302 , still error callback ajax request directly afterwards http status 0 , message "error".

enter image description here

enter image description here

ajax request code

function get(url, json) {     var args = {         type: 'get',         url: url,         // async: false,         // crossdomain: true,         xhrfields: {             withcredentials: false         },         success: function(response) {             console.debug(url, response);         },         error: function(xhr) {             console.error(url, xhr.status, xhr.statustext);         }     };     if (json) {         args.contenttype = 'application/json'     }     $.ajax(args); }  function post(url, json, data, dataencode) {     var args = {         type: 'post',         url: url,         // async: false,         crossdomain: true,         xhrfields: {             withcredentials: false         },         beforesend: function(xhr){             // added default             // ignoring prevents preflight - expects browser follow 302 location change             xhr.setrequestheader('x-requested-with', 'xmlhttprequest');             xhr.setrequestheader("x-ajax-call", "true");         },         success: function(data, textstatus, xhr) {             // var location = xhr.getresponseheader('location');             console.error('success', url, xhr.getallresponseheaders());         },         error: function(xhr) {             console.error(url, xhr.status, xhr.statustext);             console.error('fail', url, xhr.getallresponseheaders());         }     }     if (json) {         args.contenttype = 'application/json'     }     if (typeof data != 'undefined') {         // send json raw in body         args.data = dataencode ? json.stringify(data) : data;     }     console.debug('args', args);     $.ajax(args); }  var loginjson = {"j_username": "username", "j_password": "password"};  // fails post('http://localhost:8080/mutopia-server/resources/j_spring_security_check', false, loginjson, false);  // works post('http://localhost/mutopia-server/resources/j_spring_security_check', false, loginjson, false);  // works get('http://localhost:8080/mutopia-server/landuses?projectid=6', true);  // works post('http://localhost:8080/mutopia-server/params', true, {     "name": "testing",     "local": false,     "generated": false,     "project": 6 }, true); 

please note - can post other url in app via cors except spring security login. i've gone through lots of articles, insight strange issue appreciated :)

i able extending usernamepasswordauthenticationfilter... code in groovy, hope that's ok:

public class corsawareauthenticationfilter extends usernamepasswordauthenticationfilter {     static final string origin = 'origin'      @override     public authentication attemptauthentication(httpservletrequest request, httpservletresponse response){         if (request.getheader(origin)) {             string origin = request.getheader(origin)             response.addheader('access-control-allow-origin', origin)             response.addheader('access-control-allow-methods', 'get, post, put, delete')             response.addheader('access-control-allow-credentials', 'true')             response.addheader('access-control-allow-headers',                     request.getheader('access-control-request-headers'))         }         if (request.method == 'options') {             response.writer.print('ok')             response.writer.flush()             return         }         return super.attemptauthentication(request, response)     } } 

the important bits above:

  • only add cors headers response if cors request detected
  • respond pre-flight options request simple non-empty 200 response, contains cors headers.

you need declare bean in spring configuration. there many articles showing how won't copy here.

in own implementation use origin domain whitelist allowing cors internal developer access only. above simplified version of doing may need tweaking should give general idea.


Comments

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -