javascript - 在 java websocket 中添加 servlet 过滤器时,会话在指定时间后没有超时
问题描述
我的一个 web 应用程序中有 websocket,用于填充通知消息。整个应用程序是一个ear 文件,其中有多个war 文件,这个websocket 端点是一个war 文件。
它包含以下内容:
@ServerEndpoint(value = "/message", configurator = WebSocketConfigurator.class)
public class WebsocketEndpoint {
@OnOpen
public void onOpen(Session session){
}
@OnClose
public void onClose() {
}
@OnError
public void error(Session session, Throwable throwable) {
}
@OnMessage
public void handleMessage(String message, final Session session) {
synchronized (session) {
if (session != null && session.isOpen()) {
int count = 2;
session.getAsyncRemote().sendText("" + count);
session.setMaxIdleTimeout(-1);
}
}
}
}
public class WebSocketConfigurator extends ServerEndpointConfig.Configurator {
private boolean isValidHost;
@Override
public boolean checkOrigin(String originHeaderValue) {
try {
URL url = new URL(originHeaderValue);
String hostName = url.getHost();
isValidHost = Utils.isValidHostName(hostName);
} catch (Exception ex){
logger.error("Error in check checkOrigin for websocket call: "+ex.getMessage());
}
return isValidHost;
}
}
我在第一次登录时调用端点,握手将发生并获取消息,然后每 2 分钟它将调用一次以获取消息,仅没有握手,因为握手已经存在 ui 如下:
var websocketUrl = new WebSocket("ws://localhost:7001/example/message");
webSocket.onopen = function() {
webSocket.send('');
}
var interval= setInterval(function() {
'pollMessage()'
}, 120*1000);
function pollMessage(){
if(wsEndPoint.readyState==1){
wsEndPoint.send('');
}
if(wsEndPoint.readyState ==2 || wsEndPoint.readyState==3){
wsEndPoint.close();
clearInterval(interval);
}
wsEndPoint.onmessage = function(message){
alert(message);
}
}
@WebServlet(urlPatterns = {"/message"})
public class MessageWebsocketServlet extends HttpServlet
{
}
以上工作正常,没有任何问题。
但我想对安全调用进行身份验证。
所以我添加了网络过滤器
@WebFilter(urlPatterns = {"/message"}, filterName = "AuthFilter",initParams = {
@WebInitParam(name = "authorizationEnabled", value = "false")
})
@ServletSecurity(httpMethodConstraints = {@HttpMethodConstraint(value = "GET")})
public class MessageWebsocketServletFilter implements Filter{
private FilterConfig config = null;
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain)
throws ServletException, IOException {
//authentication logic goes here and it involved cross origin check and
}
@Override
public void destroy() {
config.getServletContext().log("Destroying SessionCheckerFilter");
}
}
我们已将 30 分钟配置为会话超时,并且当用户登录并空闲超过 30 分钟时添加上述过滤器后,应用程序不会导致会话超时。
任何指针都会对我有很大帮助。
解决方案
精简版:
据我所知,这是因为线session.setMaxIdleTimeout(-1);
长版:
打开 websocket 连接时,客户端会进行握手。遵循 websocket 圣经(RFC 6455 第 1.3 节),握手从HTTP
通信开始。
但是,一旦握手成功,通信就会切换到另一个协议,如下所述:
HTTP/1.1 101 交换协议
升级:websocket
连接:升级
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
通信不再是 HTTP。据我所知,Java Servlet 只处理 HTTP 通信。因此,任何有关 servlet 的配置都不会影响 websocket 配置。
推荐阅读
- css - semantic-ui-react 如何在网格内使用表单组
- python-3.x - 如果我将 2 个变量分开,我怎么能做到这一点,它总是四舍五入?
- python - Django:在表单中选择json文件并在视图中解析它
- html - 如何使用 HTML、CSS 和 Bootstrap 集中两个框
- php - Laravel 实时定位跟踪?
- git - 如何“忽略”远程仓库中的文件,以便在更新本地副本时不包含它们?
- arrays - Comparison of two arrays in Lazarus
- pandas - PANDAS:按月对分类变量进行分组、过滤和绘图
- python - 如何制作二维阵列(从帧中获取像素颜色)
- c++11 - C++11 将 lambda 表达式注入类