Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you authenticate using the Jersey Client against a JAAS enabled web-server?

Tags:

java

maven

jersey

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 am using the client part as a test.

On the server side users are authenticated through a form with Basic authentication handled via JAAS. Obviously, users need to be authenticated before being able to view certain pages.

I would like to be able to login via the Jersey before trying to access a secured page. How can this be done? I have checked that you can define a filter, but I'm not quite sure how to use that. And -- once the user is logged in via the form, how can I proceed (from the client-side) to the page I'm actually interested in?

I would really appreciate it, if somebody could show me an example how this is done on the client side with Jersey.

I have the following JUnit test case method:

@Test
public void testLogin()
        throws IOException
{
    String URL_LOGIN = "http://localhost:9080/foo/auth.html";
    Client client = Client.create();

    String username = "me";
    String password = "me";

    final HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter(username, password);
    client.addFilter(authFilter);
    client.addFilter(new LoggingFilter());

    WebResource webResource = client.resource(URL_LOGIN);
    // I even tried:
    // webResource.header("Authorization", "Basic " + "base64encoded_userid:password").type("application/xml");

    String page = webResource.post(String.class);

    System.out.println(page);
}

Please, note:

1) http://localhost:9080/foo/auth.html is the page I am supposed to be seeing upon successful auth.

2) I am actually seeing the output of http://localhost:9080/foo/login.html.

3) Obviously, through a browser, I can successfully login via the login.html page.

What do I seem to be missing out here?

like image 290
carlspring Avatar asked Mar 13 '12 00:03

carlspring


People also ask

What is the use of jersey client?

Jersey is an open source framework for developing RESTFul Web Services. It also has great inbuilt client capabilities. In this quick tutorial, we will explore the creation of JAX-RS client using Jersey 2. For a discussion on the creation of RESTful Web Services using Jersey, please refer to this article.

What is COM sun Jersey API client?

4 API. Packages. com.sun.jersey.api.client. Provides support for client-side communication with HTTP-based RESTful Web services.


3 Answers

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.

like image 196
Martin Matula Avatar answered Sep 25 '22 08:09

Martin Matula


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

  • 1. Handle cookies (unless you force URL rewriting which is unlikely)
  • 2. Detect when they get a 302 and login form back on the request and complete the required Form post before they continue.
This is true for any HTTP call (AJAX, REST, etc...) and please note that the fact that your server is using JAAS or another authentication and authorization mechanism has no bearing: it is a session management issue.

Alternatively, a Jersey specific solution is available by intercepting the calls, here:

How to get jersey logs at server?

like image 20
Bruno Grieder Avatar answered Sep 25 '22 08:09

Bruno Grieder


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);
like image 27
milosz Avatar answered Sep 24 '22 08:09

milosz