spring框架下基于websocket握手的拦截器配置(HandshakeInterceptor)
本次博客为记录小程序开发过程中遇到的问题,总结一些经验!对于拦截器的配置,相信很多人都会碰到坑,当然遇到的坑越多,你的技能提升的越快,我觉得是对的。做项目是可以提升一个程序员的技能,考验开发能力的最好方法之一。下面直接进入正题:本次拦截器的配置主要是要实现在websocket握手前,对用户信息的验证及筛选。在本系统中原先已实现了登录验证的拦截器,即判断小程序请求头中是否存在登录态...
本次博客为记录小程序开发过程中遇到的问题,总结一些经验!
对于拦截器的配置,相信很多人都会碰到坑,当然遇到的坑越多,你的技能提升的越快,我觉得是对的。做项目是可以提升一个程序员的技能,考验开发能力的最好方法之一。
下面直接进入正题:
本次拦截器的配置主要是要实现在websocket握手前,对用户信息的验证及筛选。
在本系统中原先已实现了登录验证的拦截器,即判断小程序请求头中是否存在登录态信息。是则通过,不是则拦截。
同样的,如果想要在websocket握手前也达到此目的,在原先的mvc拦截器下加入是不行的,针对websocket官方有参考的接口HandshakeInterceptor,所以应该另外配置此拦截器。网上也有很多教程可以看,可以参考Java整合WebSocket实现实时推送(注解版)写的非常不错。
当然,该博客只是介绍了基本的配置,想要完成具体的配置还需完善。
A、
因为要区分login拦截器,我们首先应该对url进行过滤,不同的url应该去往不同的拦截器,首先在web.xml中添加<url-pattern></url-pattern>
<!-- 前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.a</url-pattern>
<url-pattern>*.c</url-pattern>
</servlet-mapping>
其中有两个<url-pattern></url-pattern>对不同的url进行过滤,程序中仅允许.a或.c结尾的url通过。
B、
接下来来到springmvc的配置文件下:
<!-- websocket握手 -->
<bean id="wxsocket" class="com.yq.handler.MessageHandler"/>
<websocket:handlers allowed-origins="*">
<websocket:mapping path="/socketConnect.c" handler="wxsocket"/>
<websocket:handshake-interceptors>
<bean class="com.yq.interceptor.WebSocketInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
添加以上配置。注解方面不是很了解,不知道行不行。
完成到这一步,在前端的wx.connectSocket下已经能够成功响应了并接入拦截器内部。
注意:
在开发中,发现很多人会遇到wss://...报错的问题,其实很简单
只需改成ws就可以了,因为wss表示的是加了SSL安全协议的请求,而开发过程中一般使用的都是本地ip。
C、
再来看HandshakeInterceptor具体配置
package com.yq.interceptor;
import java.util.Collection;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import com.yq.utils.RedisUtil;
/*
* websocket连接拦截器
*/
public class WebSocketInterceptor extends HttpSessionHandshakeInterceptor{
@Autowired
RedisUtil redisUtil;
/*
* 握手后
* @see org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor#afterHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.lang.Exception)
*/
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("对方正在输入...");
}
/*
* 握手前
* @see org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor#beforeHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.util.Map)
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
HttpHeaders headers = request.getHeaders();
String sessionid = headers.getFirst("sessionid");
System.out.println("拦截器获取的sessionid"+sessionid);
if(sessionid!=null && sessionid != "") {
//检查是否存在
if(redisUtil.isExist(sessionid)) {
System.out.println("通过不拦截");
response.setStatusCode(HttpStatus.OK);
return true;
}
//session过期拦截
System.out.println("拦截请求1:sessionid已过期!");
response.setStatusCode(HttpStatus.FORBIDDEN);
return false;
}
System.out.println("拦截请求2:sessionid为空");
response.setStatusCode(HttpStatus.FORBIDDEN);
return false;
}
@Override
public Collection<String> getAttributeNames() {
// TODO Auto-generated method stub
return super.getAttributeNames();
}
@Override
public boolean isCopyAllAttributes() {
// TODO Auto-generated method stub
return super.isCopyAllAttributes();
}
@Override
public boolean isCopyHttpSessionId() {
// TODO Auto-generated method stub
return super.isCopyHttpSessionId();
}
@Override
public boolean isCreateSession() {
// TODO Auto-generated method stub
return super.isCreateSession();
}
@Override
public void setCopyAllAttributes(boolean copyAllAttributes) {
// TODO Auto-generated method stub
super.setCopyAllAttributes(copyAllAttributes);
}
@Override
public void setCopyHttpSessionId(boolean copyHttpSessionId) {
// TODO Auto-generated method stub
super.setCopyHttpSessionId(copyHttpSessionId);
}
@Override
public void setCreateSession(boolean createSession) {
// TODO Auto-generated method stub
super.setCreateSession(createSession);
}
}
D、
最后来看下实际效果
1、第一次登录:
前端显示连接失败,是因为第一次登录不存在登录态,设置登录态30s时间。此时需要提醒用户运行登录
后台运行结果也显示了相关信息
拦截器获取的sessionid
拦截请求2:sessionid为空
2、模拟长时间未登录,登录态过期(30s):
同样的过期的用户不可以连接,需要重新登陆,此时需要提醒用户重新登录
后台运行结果,过期
拦截器获取的sessionid6574123103e869e00d24b4071f1fb6ce
拦截请求1:sessionid已过期!
3、处于登录状态
可以看到成功连接并发送信息了
后台运行结果
拦截器获取的sessionid894ca3ec8fe8507b516e659a9e4a464f
通过不拦截
对方正在输入...
。。。websocket已连接
message:有消息请接收..发送中
。。。websocket已断开连接
其中HttpSessionHandshakeInterceptor为官方给出的HandshakeInterceptor接口的实现类。
那么这里主要是对beforeHandshake()握手前进行拦截处理的介绍
如果大家想要了解更多的信息可以去参考该接口的源码,简单易懂。
以上就是我HandshakeInterceptor配置的全部内容,拦截逻辑上可能不是很严谨,希望大家看到的可以指点指点。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)