与Java客户端实现的Spring Security(Implementing Spring Sec

2019-07-20 14:30发布

客户端

我有一个基本的使用POST或GET方法连接到远程服务器的Java应用程序:

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();

(我不能改变这个代码,唯一的东西,我可以改变的是urlStrdata调用方法时发送到服务器)。

[编辑],客户端可以是一个Java客户端或任何其他客户端(C ++,目标c,...)。 这里的关键是,我只能访问什么在我的帖子的正文以及网址。

服务器端

在我的服务器端,我想实现的Spring Security(SecurityContext中和会话持久性)。

据我所知,春天的安全性是基于浏览器的Cookie当它是一个WebApp ,以保存有关信息session id 。 但对我来说没有任何浏览器。

  • 我需要模拟的存储JSESSIONID ,并将其发送回服务器? 我不知道这是可能的,因为我需要调用conn.addRequestProperty(key, value)这是不可能的。

  • 有没有其他办法?

谢谢。

[编辑]

由@zagyi指出的那样,我就可以使用URL会话令牌传递到春天,但我仍然无法弄清楚如何。

Answer 1:

在url中传递的JSESSIONID只是在这样的URL的末尾追加它的事情:

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

如果您配置的浏览器不接受任何Cookie,在这种情况下,服务器会自动包含在URL中的会话ID(假设默认配置Tomcat),你可以在工作的看到这一点。 这个话题也讨论了这个问题 。



Answer 2:

可存在用于该客户端的解决方案。

行动点,我们可以互动是在这里:

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

我们将提供自己的(包裹) HttpURLConnection ,它将处理JSESSIONID 。 但不幸的是,我们必须进一步启动了一下。

诀窍是,我们注册一个新的协议,如“xhttp”,我们用它来包装一个真正的“HTTP”协议连接。 所以,你的URL看起来像:

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

首先,定义一个URLStreamHandlerFactory

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

在Java(或应用程序)初始化时,我们可以设置它。 你可以这样做只有一次每个JVM。

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

所以,让我们继续用MyURLStreamHandler

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

这是非常简单的,我们创造我们自己的连接。 让我们做的脏东西:

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");
    }
}

瞧,我们成功地访问我们的连接,并设置JSESSIONID头。

所有你需要的是编译的类,类文件添加到客户端罐子,使运行在上面的代码运行在同一个JVM某种方式初始化代码。

如果你不能做到这一点,还有另外一种可能:设置以下系统参数到客户端Java应用程序:

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

在这种情况下创建一个com.example.myprotocol.xhttp (xhttp喜欢你的协议名称),我们重命名MyURLStreamHandlercom.example.myprotocol.xhttp.Handler 。 这是固定的名称,其中协议解析器将寻找它。 请注意,这java.protocol.handler.pkgs属性由安全管理检查。



文章来源: Implementing Spring Security with Java Client