2

Client Side

I have a java application that connects to a remote server using basic POST or GET methods:

URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setAllowUserInteraction(false);
conn.setRequestProperty("Content-type", "text/xml; charset=" + ENCODING);

conn.connect();
conn.getOutputStream().write(data.getBytes(ENCODING));
conn.getOutputStream().close();

(I cannot change this code, the only things I can change is the urlStr and the data sent to the server when calling the method).

[EDIT] : The client can be a java client or any other client (c++, objective-c, ..). The point here is that I can only access what's in the body of my post as well as the URL.

Server Side

On my server side, I would like to implement Spring Security (SecurityContext and session persistance).

I understand that spring security is based on the browser's cookies when it's a WebApp to hold the information about the session id. But in my case there's no Browser.

  • Do I need to simulate the storage of the JSESSIONID and send it back to the server? I'm not sure this is possible since I would need to call conn.addRequestProperty(key, value) which is not possible.

  • Is there any other way?

Thank you.

[EDIT]

as pointed out by @zagyi, I can use the URL to pass session token to Spring, but I still can't figure out how.

6
  • You have to be able to pass some information based on which the request gets authenticated on the server side. If it's not a cookie, it might be a basic auth header, but that's not much different from a cookie from your perspective... Commented Feb 26, 2013 at 18:45
  • so you're suggesting that i send a token to my client, which will be sent whenever it makes a request to the server (like the JSESSIONID token). But how do I generate this token from the server side and how can I check it against stored sessions ? Commented Feb 26, 2013 at 18:48
  • Option1 is to store JSESSIONID on the client after a successfull login, and resend that form client to server with each request. Option2 is that the clien sends credentials with each request in an auth header, and then there is no need for session handling. Commented Feb 26, 2013 at 18:56
  • thanks for the reply. Option 1 : where do I get the JSESSIONID on the server, and having a JSESSIONID how do I get the corresponding session ? Option 2: For each authentication I need to check in a DB, so checking for every request will consume lots of resources. Commented Feb 26, 2013 at 19:06
  • You can pass the session id from the client in the url, then your servlet container processes it, and makes the session available to your webapp. Spring Security components will access the session throught the http request object. But this is all implemented, you only need to properly configure it. Commented Feb 26, 2013 at 19:38

2 Answers 2

2
+50

Passing the jsessionid in the url is just a matter of appending it at the end of the url like this:

http://localhost:8080/example/auth/login;jsessionid=A06F00609BBA8A4C2B005FB25F90C4C9

You can see this in working if you configure a browser not to accept any cookies, in which case the server automatically includes the session id in the url (assuming a default tomcat configuration). This topic is also discussed in this question.

Sign up to request clarification or add additional context in comments.

1 Comment

Yep I just found this solution few hours earlier, I send the session id back to the client in the response body which sends it back to the server on the url.
1

There may be a client-side solution for that.

The action point where we can interact is here:

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

We will provide an own (wrapped) HttpURLConnection, which will handle the JSESSIONID. But unfortunately we have to start a bit further.

The trick is that we register a new protocol, e.g. "xhttp", that we use to wrap a real "http" protocol connection. So, your URL will look like:

xhttp://www.example.com/...

First, define a URLStreamHandlerFactory class

public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory {
    public URLStreamHandler createURLStreamHandler(String protocol) {
        if ("xhttp".equals(protocol)) {
            return new MyURLStreamHandler();
        }
        return null;
    }
}

At Java (or application) init time we can set it. You can do it only once per JVM.

URLStreamHandlerFactory fac = new MyURLStreamHandlerFactory();
URL.setURLStreamHandlerFactory(fac);

So, let's go ahead with MyURLStreamHandler.

public class MyURLStreamHandler extends URLStreamHandler {
    @Override
    protected URLConnection openConnection(URL url) throws IOException {
        return new MyHttpURLConnection(url);
    }
}

This is quite simple, we create our own connection. Let's do the dirty stuff:

public final class MyHttpURLConnection extends HttpURLConnection {
    private HttpURLConnection conn;
    public MyHttpURLConnection(URL url) throws MalformedURLException, IOException {
        super(url);
        String newUrlString = url.toExternalForm().substring(1);
        conn = (HttpURLConnection) new URL(newUrlString).openConnection();
    }
    @Override
    public void disconnect() {
        conn.disconnect();
    }
    @Override
    public boolean usingProxy() {
        return false;
    }
    @Override
    public void connect() throws IOException {
        conn.connect();
        conn.setRequestProperty("JSESSIONID", "X");
    }
}

And voilá, we managed to access our connection, and set the JSESSIONID header.

All you need is to compile your classes, add the class files to the client jar, and make the init code running some way in the same JVM where the above code runs.

If you cannot do it, there is another possibility: set the following system parameter to the client Java application:

-Djava.protocol.handler.pkgs=com.example.myprotocol

In this case create a com.example.myprotocol.xhttp (xhttp like your protocol name), and rename our MyURLStreamHandler class to com.example.myprotocol.xhttp.Handler. This is the fixed name where the protocol resolver will look for it. Note, that this java.protocol.handler.pkgs property is checked by the security manager.

1 Comment

thank you very much for your reply.. now I should have mentioned that the reason why I can't change the Client's java code is that it's only one implementation amongs others (i'm using PlayN which is a multiplatform library that provides interfaces for different types of platform). So if this works with the java client there no way i can implement it for iPhone clients.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.