2

客户端

我有一个使用基本 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++、objective-c、..)。这里的重点是我只能访问我的帖子正文中的内容以及 URL。

服务器端

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

我了解 Spring Security 是基于浏览器的 cookieWebApp来保存有关session id. 但就我而言,没有浏览器。

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

  • 还有其他方法吗?

谢谢你。

[编辑]

正如@zagyi 所指出的,我可以使用 URL 将会话令牌传递给 Spring,但我仍然不知道如何。

4

2 回答 2

2

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

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

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

于 2013-03-03T18:12:59.913 回答
1

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

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

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.xhttpxhttp就像您的协议名称一样),并将我们的MyURLStreamHandler类重命名为com.example.myprotocol.xhttp.Handler. 这是协议解析器将在其中查找它的固定名称。请注意,此java.protocol.handler.pkgs属性由安全管理器检查。

于 2013-03-03T00:09:36.663 回答