3

I have a REST based web service running in my Tomcat Java EE servlet container.

I am writing a jquery client that is from another domain and is therefore using CORS. It hits the login web service, followed by another call. I originally implemented these two calls using getJSON and the calls were working fine, but I wasn't getting the JSESSIONID cookie to stay on the second call, so the web service had an unauthenticated session and threw and error.

After doing research, I ran across doing ajax withCredentials and thought that this is what I needed to do. The AJAX login call failed in preflight.

So, when I sniff the traffic to my webserver, the getJSON calls run as two gets and look fine except that the cookie doesn't come back with the second call. When I run the ajax call, it does an OPTIONS call to my server, gets a 200 status back on the client and then fails inside of jQuery for reasons I can't seem to find.

var jqxhr = jQuery.getJSON(loginUrl, {
  xhrFields: {
      withCredentials: true
  },
  crossDomain: true
})
.done(function(response) {
    AgileJurySessionKey = response;
    AgileJuryLoggedIn = true;
    doneCallback();
})
.fail(function() {
    failCallback();
});

Here is the AJAX version of the same call:

jQuery.ajax(loginUrl, {
    type: "GET",
    contentType: "application/json; charset=utf-8",
    success: function(data, status, xhr) {
        alert(data);
        doneCallback;
    },
    error: function(jqxhr, textStatus, errorThrown) {
        alert(errorThrown);
        failCallback;
    },
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true
});

What's different between these two?

Here's the filter I put in to the web server for CORS:

/**
 * This filter allows access to our web services from clients that are not on the local domain
 * 
 * @author Xerox
 */
public class CorsFilter extends OncePerRequestFilter {

  /* (non-Javadoc)
   * @see org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)
   */
  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
          throws ServletException, IOException {
      response.addHeader("Access-Control-Allow-Origin", "*");
      if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
          // CORS "pre-flight" request
          response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
          response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Set-Cookie");
          response.addHeader("Access-Control-Max-Age", "1800");//30 min
      }
      filterChain.doFilter(request, response);
  }
}
Arjan Tijms
  • 36,666
  • 12
  • 105
  • 134
Thom
  • 11,254
  • 22
  • 91
  • 152

3 Answers3

4
jQuery.getJSON(loginUrl, {
  xhrFields: {
      withCredentials: true
  },
  crossDomain: true
})

The second parameter of $.getJSON is the data you want to send, not an options object. To use those, you will need to call $.ajax directly.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • 2
    I tried this but it was setting xhrFields withCredentials to true globally that helped me. See http://stackoverflow.com/a/29138912/59996 – Aligma Apr 29 '16 at 06:35
1

getJSON isn't really a method, it's just a convenience function that is basically a shortcut for:

$.ajax({
  dataType: "json",
});

So basically, $.getJSON() should behave the same as $.ajax() with the dataType set to "json"

Matthew Graves
  • 2,956
  • 1
  • 14
  • 20
0

Due to continual issues with CORS, I finally gave up on this one as intractable and worked the problem from the other end.

I used a session key coming back to track the length of the session and then re-attaching security based on this, which is how I'd designed security to work in the first place.

Thom
  • 11,254
  • 22
  • 91
  • 152