Implementing Spring Security with Java Client

╄→гoц情女王★ 提交于 2019-12-01 09:54:18

问题


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.


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/15096764/implementing-spring-security-with-java-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!