I have the following scenario:
Server: Jetty (with configured JAAS)
Client: Jersey invoked via JUnit (via Maven)
I have JAAS set up in the web server
I do not use Jersey but this is not a Jersey issue per se.
First, you must be using either FORM login or BASIC authentication; unless this is a custom development I doubt you are using a 'Form with Basic Authentication'.
If you are using Basic Authentication, then things are pretty simple (though inefficient): BASIC authentication is stateless and you must send the Authorization: Basic xxxx HTTP header on EVERY request.
If you are using FORM login, things a re a bit more involved. On every request, you are supposed to send the Session Id (stored in a Cookie or using URL rewriting). If you do not send one, or if the associated session is invalidated (because it is expired for instance), the server will send a 302 (redirect) and the Login Form. You are then supposed to perform a FORM POST to the URL indicated in the form with the username and password as parameters. If authentication is successful, the server will then send the response to the original request (and a new session id). In this scenario, programmatic request must therefore be able to
Alternatively, a Jersey specific solution is available by intercepting the calls, here:
How to get jersey logs at server?
To access Rest End Point from Form Based Authentication One need to register a Form Authentication Filter with the JAX-RS Jersey client. One useful filter class is given at the following git hub link.
https://github.com/imixs/imixs-melman/blob/master/src/main/java/org/imixs/melman/FormAuthenticator.java
use FormAuthenticator.java in your project and in Rest Jersey client do the following:
// Constructor of jersey Rest client
public RestClass(String username, String password)
{
private WebTarget webTarget;
private Client client;
private static final String BASE_URI = "http://localhost:8080/SampleRest/webresources";
client = javax.ws.rs.client.ClientBuilder.newClient();
client.register(new FormAuthenticator(BASE_URI, user, password));
webTarget = client.target(BASE_URI).path("restpath");
}
And everything works fine. I have used it and this issue is solved. JAX-RS API must give this authenticator in their release.
Note: same username and password which were used in form based authentication are to be supplied from calling client in servlets.
as RestClient rs = new RestClient(username, password);
** Aplication class should register RolesAllowedDynamicFeature for roles to take effect ** MyApplication.java in Web Project where Rest class and FormAuthenticator.java resides rest package
@ApplicationPath("webresources")
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("entity.service");
packages("rest");
register(RolesAllowedDynamicFeature.class);
}
}
With Basic auth you don't need to go to any login page at all. If the server is configured to use Basic auth, then you can make requests to any protected page if you include the basic auth header in your requests. The Jersey filter takes care of that. So, if Basic auth would really be what the server is using, then your code should work.
Given it does not work and the way it does not work I am pretty sure the server is configured to use form-based authentication instead of the basic authentication.
For the form-based authentication to work, you'll have to send a post request with form data including user name and password to log in and then set cookies you receive from the server to your subsequent requests (since the server - once you log in - will set the session cookie).
Look at how the login.html looks like - it should contain a form. If it is using the standard servlet form auth., the action URL of that form should be "j_security_check" and there should be two form parameters: j_username and j_password. If that is the case, you can try something like the following:
String URL_LOGIN = "http://localhost:9080/foo/j_security_check";
String URL_DATA = "http://localhost:9080/foo/auth.html";
Client client = Client.create();
// add a filter to set cookies received from the server and to check if login has been triggered
client.addFilter(new ClientFilter() {
private ArrayList<Object> cookies;
@Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
if (cookies != null) {
request.getHeaders().put("Cookie", cookies);
}
ClientResponse response = getNext().handle(request);
// copy cookies
if (response.getCookies() != null) {
if (cookies == null) {
cookies = new ArrayList<Object>();
}
// A simple addAll just for illustration (should probably check for duplicates and expired cookies)
cookies.addAll(response.getCookies());
}
return response;
}
});
String username = "me";
String password = "me";
// Login:
WebResource webResource = client.resource(URL_LOGIN);
com.sun.jersey.api.representation.Form form = new Form();
form.putSingle("j_username", username);
form.putSingle("j_password", password);
webResource.type("application/x-www-form-urlencoded").post(form);
// Get the protected web page:
webResource = client.resource(URL_DATA);
String response = webResource.get(String.class);
I haven't tested this, so maybe there will be some typos or bugs.
For me these changes solved the issue:
String URL_LOGIN = "http://localhost:9080/foo/j_security_check";
String URL_DATA = "http://localhost:9080/foo/auth.html";
Client client = Client.create();
// add a filter to set cookies received from the server and to check if login has been triggered
client.addFilter(new ClientFilter() {
private ArrayList<Object> cookies;
@Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
if (cookies != null) {
request.getHeaders().put("Cookie", cookies);
}
ClientResponse response = getNext().handle(request);
// copy cookies
if (response.getCookies() != null) {
if (cookies == null) {
cookies = new ArrayList<Object>();
}
// A simple addAll just for illustration (should probably check for duplicates and expired cookies)
cookies.addAll(response.getCookies());
}
return response;
}
});
String username = "me";
String password = "me";
// Get the protected web page: (this will make the server know that someone will try to access the protected resource)
WebResource webResource = client.resource(URL_DATA);
String response = webResource.get(String.class);
// Login:
webResource = client.resource(URL_LOGIN);
com.sun.jersey.api.representation.Form form = new Form();
form.putSingle("j_username", username);
form.putSingle("j_password", password);
webResource.type("application/x-www-form-urlencoded").post(form);
// Get the protected web page: (this time the service will return the data)
webResource = client.resource(URL_DATA);
response = webResource.get(String.class);
Autorization for JAAS:
String URL_DATA = "http://localhost:9080/foo/auth.html";
Client client = Client.create();
String username = "me";
String password = "me";
client.addFilter(new HTTPBasicAuthFilter(username, password));
// Get the protected web page:
WebResource webResource = client.resource(URL_DATA);
String response = webResource.get(String.class);
System.out.println(response);