如何从 Java websocket 服务器访问客户端主机名、http headers 等?
How to access client hostname, http headers etc from a Java websocket server?
我已经学习了许多教程和示例示例代码,但我还没有看到像我们在 Servlet 请求 object 中那样访问客户端的 HTTP header、主机名等的方法。
我该怎么做?
假设我将 onOpen 定义为-
@OnOpen
public void onOpen(Session session) {
}
在上述方法中,有没有一种方法可以使用 session 字段访问底层 HTTP 连接详细信息?即使我可以访问底层 Servlet(如果有的话)我也可以
参见第 4.1.1.5 章 Tyrus user guide. It requires some amount of work to get the info from ServerEnpointConfig.Configurator to endpoint instance, but it can be done. (see ModifyRequestResponseHeadersTest.java)
基于link1
和 link2
我终于想通了我们可以通过以下两个类获取客户端IP,实际上您可以使用暴露的httpservletRequest做更多的事情...
ServletAwareConfigurator .java
package examples;
import java.lang.reflect.Field;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
public class ServletAwareConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpServletRequest httpservletRequest = getField(request, HttpServletRequest.class);
String sClientIP = httpservletRequest.getRemoteAddr();
config.getUserProperties().put("clientip", sClientIP);
// ...
}
//hacking reflector to expose fields...
private static < I, F > F getField(I instance, Class < F > fieldType) {
try {
for (Class < ? > type = instance.getClass(); type != Object.class; type = type.getSuperclass()) {
for (Field field: type.getDeclaredFields()) {
if (fieldType.isAssignableFrom(field.getType())) {
field.setAccessible(true);
return (F) field.get(instance);
}
}
}
} catch (Exception e) {
// Handle?
}
return null;
}
}
GetHttpSessionSocket.java
package examples;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/example",
configurator = ServletAwareConfigurator.class)
public class GetHttpSessionSocket {
private Session wsSession;
private String sClientIP;
@OnOpen
public void open(Session session, EndpointConfig config) {
this.wsSession = session;
this.sClientIP = (String) config.getUserProperties()
.get("clientip");
}
@OnMessage
public void echo(String msg) throws IOException {
wsSession.getBasicRemote().sendText(msg);
}
}
我已经学习了许多教程和示例示例代码,但我还没有看到像我们在 Servlet 请求 object 中那样访问客户端的 HTTP header、主机名等的方法。
我该怎么做?
假设我将 onOpen 定义为-
@OnOpen
public void onOpen(Session session) {
}
在上述方法中,有没有一种方法可以使用 session 字段访问底层 HTTP 连接详细信息?即使我可以访问底层 Servlet(如果有的话)我也可以
参见第 4.1.1.5 章 Tyrus user guide. It requires some amount of work to get the info from ServerEnpointConfig.Configurator to endpoint instance, but it can be done. (see ModifyRequestResponseHeadersTest.java)
基于link1 和 link2
我终于想通了我们可以通过以下两个类获取客户端IP,实际上您可以使用暴露的httpservletRequest做更多的事情...
ServletAwareConfigurator .java
package examples;
import java.lang.reflect.Field;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
public class ServletAwareConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpServletRequest httpservletRequest = getField(request, HttpServletRequest.class);
String sClientIP = httpservletRequest.getRemoteAddr();
config.getUserProperties().put("clientip", sClientIP);
// ...
}
//hacking reflector to expose fields...
private static < I, F > F getField(I instance, Class < F > fieldType) {
try {
for (Class < ? > type = instance.getClass(); type != Object.class; type = type.getSuperclass()) {
for (Field field: type.getDeclaredFields()) {
if (fieldType.isAssignableFrom(field.getType())) {
field.setAccessible(true);
return (F) field.get(instance);
}
}
}
} catch (Exception e) {
// Handle?
}
return null;
}
}
GetHttpSessionSocket.java
package examples;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/example",
configurator = ServletAwareConfigurator.class)
public class GetHttpSessionSocket {
private Session wsSession;
private String sClientIP;
@OnOpen
public void open(Session session, EndpointConfig config) {
this.wsSession = session;
this.sClientIP = (String) config.getUserProperties()
.get("clientip");
}
@OnMessage
public void echo(String msg) throws IOException {
wsSession.getBasicRemote().sendText(msg);
}
}