使用Java客户端实现Spring Security

客户端

我有一个使用基本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(); 

(我无法更改此代码,我可以更改的唯一内容是urlStr和调用方法时发送到服务器的data )。

[编辑] :客户端可以是java客户端或任何其他客户端(c ++,objective-c,..)。 这里的要点是我只能访问post正文中的内容以及URL。

服务器端

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

我知道Spring安全性是基于浏览器的cookie,当它是一个WebApp来保存有关session id的信息时。 但就我而言,没有浏览器。

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

  • 还有别的办法吗?

谢谢。

[编辑]

正如@zagyi所指出的,我可以使用URL将会话令牌传递给Spring,但我仍然无法弄清楚如何。

在url中传递jsessionid只是将其附加到url的末尾,如下所示:

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

如果您将浏览器配置为不接受任何cookie,则可以看到此情况,在这种情况下,服务器会自动在URL中包含会话ID(假设使用默认的tomcat配置)。 本问题还讨论了该主题。

可能有一个客户端解决方案。

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

 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标头。

您所需要的只是编译您的类,将类文件添加到客户端jar,并使init代码在运行上述代码的同一JVM中以某种方式运行。

如果您不能这样做,还有另一种可能性:将以下系统参数设置为客户端Java应用程序:

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

在这种情况下,创建一个com.example.myprotocol.xhttp (类似于您的协议名称的xhttp ),并将MyURLStreamHandler类重命名为com.example.myprotocol.xhttp.Handler 。 这是协议解析器将查找的固定名称。 请注意,安全管理器会检查此java.protocol.handler.pkgs属性。