Tomcat WebSocket服务器获取客户端IP地址

根据JFR-356,Tomcat提供的WebSocket API并没有获取客户端IP地址的方法。所以我们无法直接在WebSocket类里面获取客户端IP地址等信息。但是通过监听ServletRequest并使用HttpSession和ServerEndpointConfig里面的Attributes传递信息,就可以实现直接在WebSocket类中获得客户端IP地址,弥补了WebSocket的一些先天不足。

废话不多说,直接上代码:

MyServletListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package ws_ip;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@WebListener()
public class MyServletListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request=(HttpServletRequest) sre.getServletRequest();
HttpSession session=request.getSession();
session.setAttribute("ClientIP", sre.getServletRequest().getRemoteAddr());//把HttpServletRequest中的IP地址放入HttpSession中,关键字可任取,此处为ClientIP
}
}

↑以上代码用来监听ServletRequest事件,发生在创建WebSocket的session之前。
MyConfigurator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
package ws_ip;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
public class MyConfigurator extends Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
config.getUserProperties().put("ClientIP", httpSession.getAttribute("ClientIP"));//把HttpSession中保存的ClientIP放到ServerEndpointConfig中,关键字可以跟之前不同
}
}

↑这段代码在@ServerEndpoint标记处运行。
ServerMain.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package ws_ip;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/main", configurator = MyConfigurator.class)//此处需要放入之前自定义的configurator类
public class ServerMain {
private Session session;
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private String ipaddr;
@OnOpen
public void onOpen(Session session) {
this.session = session;
ipaddr=(String) session.getUserProperties().get("ClientIP");//将客户端IP地址从WebSocket的session中取出
System.out.println("Incoming connection from "+ipaddr);
}
@OnClose
public void onClose() {
System.out.println("Connection from "+ipaddr+" closed");
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println(sdf.format(new Date())+" - "+ipaddr + " - " + message);
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
}

运行效果:

参考资料:JSR-356 WebSockets with Tomcat - How to limit connections within single IP address?
文章目录
|