fferrandini
fferrandini

Reputation: 101

Jersey REST + CORS + Jquery AJAX CALL

I'm building up a jersey rest api , using jersey 1.8 , tomcat 7 and spring 4

this service will have Basic HTTP authentication and will provide the info for any origin( it will be used by our customers from different domains..) so, CORS is enabled using jersey own structure.

I got an implementation for ContainerResponseFilter that sets Access-Control-Allow-Origin and Access-Control-Request-Headers headers.

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;

public class ResponseCorsFilter implements ContainerResponseFilter{

@Override
public ContainerResponse filter(ContainerRequest req,
        ContainerResponse contResp) {
    // TODO Auto-generated method stub
    ResponseBuilder resp = Response.fromResponse(contResp.getResponse());
    resp.header("Access-Control-Allow-Origin", "*")
            .header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");

    String reqHead = req.getHeaderValue("Access-Control-Request-Headers");

    if(null != reqHead && !reqHead.equals("")){
        resp.header("Access-Control-Allow-Headers", reqHead);
    }

    contResp.setResponse(resp.build());
    return contResp;
}

}

And i got this implementation of ContainerRequestFilter which takes care of the Authentication process.

public class BasicAuthFilter implements ContainerRequestFilter{

@Override
public ContainerRequest filter(ContainerRequest containerRequest) throws WebApplicationException {
    // TODO Auto-generated method stub

     String method = containerRequest.getMethod();
     String path = containerRequest.getPath(true);

     //pode resgatar o WADL do webservice
     if(method.equals("GET") && (path.equals("application.wadl") || path.equals("application.wadl/xsd0.xsd"))){
         return containerRequest;
     }

     //pego o header
     String auth = containerRequest.getHeaderValue("Authorization"); //already tried "authorization"

     MultivaluedMap<String,String> headers = containerRequest.getRequestHeaders();
     for (Entry<String,List<String>> e : headers.entrySet()) {
         System.out.println("###################### " + e.getKey() + " / " + e.getValue());
     }


     //quem tentou usar nosso webservice sem credenciais de usuario, tchau!
     if(auth == null){
         System.out.println("############################# header not found");
         throw new WebApplicationException(Status.UNAUTHORIZED);
     }

    //lap 
    List<String> lap = Arrays.asList(ClarkeUtil.decode(auth));

    //se algo deu errado no lap
    if(lap == null || lap.size() != 2){
       throw new WebApplicationException(Status.UNAUTHORIZED);
    }

    System.out.println("###################################### " + lap.get(0)+":"+lap.get(1));


    //my database checking user:password still not implemented
    //...


  return containerRequest;

}

}

my testing jquery ajax call which is fired from a simple local webserver called miniweb.

<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
   $.ajax({
     type: "GET",   
     url: "http://localhost:8080/pushrpi/welcome/fernando",
     dataType: "text/html",
     crossDomain: true,
     headers: {
        "Authorization": "Basic ZGVwb3NlY2xpZW50OmRlcG9zZWNsaWVudA=="
     }
   }).done(function(data){ $("#conteudo").html(data)});
 </script>
 </head>

<body>
<div id="conteudo"></div>
</body>
</html>

my tomcat console log for "for" statement in BasicAuthFilter filter.

###################### host / [localhost:8080]
###################### connection / [keep-alive]
###################### cache-control / [max-age=0]
###################### access-control-request-method / [GET]
###################### origin / [null]
###################### user-agent / [Mozilla/5.0 (Windows NT 5.1) AppleWebKit/53
7.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36]
###################### access-control-request-headers / [accept, authorization]
###################### accept / [*/*]
###################### accept-encoding / [gzip,deflate,sdch]
###################### accept-language / [pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4]

In jquery ajax call if i dont use the headers , this "###################### access-control-request-headers / [accept, authorization]" doesnt show up in tomcat console . So somehow it is "activating" the authentication header.

Why when i execute the line below i'm always getting null ?

String auth = containerRequest.getHeaderValue("authorization");

When i disable BasicAuthFilter, i get my hello world message. So jersey+spring is working.

this is my log using chrome webdeveloper: Request:

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/pushrpi/welcome/fernando
Request Method:OPTIONS
Status Code:401 Unauthorized
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, authorization
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:8000
Pragma:no-cache
Referer:http://localhost:8000/teste2.html
 User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko)    Chrome/36.0.1985.143 Safari/537.36



Response :

Access-Control-Allow-Headers:accept, authorization
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Content-Language:en
Content-Length:975
Content-Type:text/html;charset=utf-8
Date:Mon, 25 Aug 2014 13:05:15 GMT
Server:Apache-Coyote/1.1

Any tips? thanks in advance!

Upvotes: 1

Views: 2166

Answers (1)

fferrandini
fferrandini

Reputation: 101

i found the solution myself.

before a GET request, is sent an OPTION request .. which doesnt contain your auth data. So what i needed to do was simple: let all OPTIONs request be executed.

just added this code snippet to my BasicAuthFilter ( it is set before the "String auth = containerRequest.getHeaderValue("authorization");" line):

     if(method.equals("OPTIONS")) {
         throw new WebApplicationException(Status.OK);
     }

after this OPTION request is executed , also is the later GET request ( which is actually your request at my jquery ajax)

hope this help people.

Upvotes: 5

Related Questions