From 940773b4e5e70c1b65e71be095632d5dc1c9182d Mon Sep 17 00:00:00 2001
From: zhangdaiscott <zhangdaiscott@163.com>
Date: Tue, 19 Jul 2022 19:11:59 +0800
Subject: [PATCH] websocket增加token校验,解决安全问题

---
 jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebSocketConfig.java                 | 15 +++++++++++++++
 jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/RequestBodyReserveFilter.java | 35 +++++++++++++++++++++++++++++++++++
 jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/WebsocketFilter.java          | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 0 deletions(-)
 create mode 100644 jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/RequestBodyReserveFilter.java
 create mode 100644 jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/WebsocketFilter.java

diff --git a/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebSocketConfig.java b/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebSocketConfig.java
index 52230f8..597e7b4 100644
--- a/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebSocketConfig.java
+++ b/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebSocketConfig.java
@@ -1,5 +1,7 @@
 package org.jeecg.config;
 
+import org.jeecg.config.filter.WebsocketFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@@ -19,4 +21,17 @@ public class WebSocketConfig {
         return new ServerEndpointExporter();
     }
 
+    @Bean
+    public WebsocketFilter websocketFilter(){
+        return new WebsocketFilter();
+    }
+
+    @Bean
+    public FilterRegistrationBean getFilterRegistrationBean(){
+        FilterRegistrationBean bean = new FilterRegistrationBean();
+        bean.setFilter(websocketFilter());
+        bean.addUrlPatterns("/websocket/*", "/eoaSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
+        return bean;
+    }
+
 }
diff --git a/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/RequestBodyReserveFilter.java b/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/RequestBodyReserveFilter.java
new file mode 100644
index 0000000..fd4f07a
--- /dev/null
+++ b/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/RequestBodyReserveFilter.java
@@ -0,0 +1,35 @@
+package org.jeecg.config.filter;
+
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.config.sign.util.BodyReaderHttpServletRequestWrapper;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * 针对post请求,将HttpServletRequest包一层 保留body里的参数
+ * @Author taoYan
+ * @Date 2022/4/25 19:19
+ **/
+public class RequestBodyReserveFilter implements Filter {
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        ServletRequest requestWrapper = null;
+
+        if(servletRequest instanceof HttpServletRequest) {
+            HttpServletRequest req = (HttpServletRequest) servletRequest;
+            // POST请求类型,才获取POST请求体
+            if(CommonConstant.HTTP_POST.equals(req.getMethod())){
+                requestWrapper = new BodyReaderHttpServletRequestWrapper(req);
+            }
+        }
+
+        if(requestWrapper == null) {
+            filterChain.doFilter(servletRequest, servletResponse);
+        } else {
+            filterChain.doFilter(requestWrapper, servletResponse);
+        }
+    }
+}
diff --git a/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/WebsocketFilter.java b/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/WebsocketFilter.java
new file mode 100644
index 0000000..89a2abc
--- /dev/null
+++ b/jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/filter/WebsocketFilter.java
@@ -0,0 +1,52 @@
+package org.jeecg.config.filter;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.CommonAPI;
+import org.jeecg.common.util.RedisUtil;
+import org.jeecg.common.util.SpringContextUtils;
+import org.jeecg.common.util.TokenUtils;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * websocket 前端将token放到子协议里传入 与后端建立连接时需要用到http协议,此处用于校验token的有效性
+ * @Author taoYan
+ * @Date 2022/4/21 17:01
+ **/
+@Slf4j
+public class WebsocketFilter implements Filter {
+
+    private static final String TOKEN_KEY = "Sec-WebSocket-Protocol";
+
+    private static CommonAPI commonApi;
+
+    private static RedisUtil redisUtil;
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        if (commonApi == null) {
+            commonApi = SpringContextUtils.getBean(CommonAPI.class);
+        }
+        if (redisUtil == null) {
+            redisUtil = SpringContextUtils.getBean(RedisUtil.class);
+        }
+        HttpServletRequest request = (HttpServletRequest)servletRequest;
+        String token = request.getHeader(TOKEN_KEY);
+
+        log.info("websocket连接 Token安全校验,Path = {},token:{}", request.getRequestURI(), token);
+
+        try {
+            TokenUtils.verifyToken(token, commonApi, redisUtil);
+        } catch (Exception exception) {
+            log.error("websocket连接校验失败,{},token:{}", exception.getMessage(), token);
+            return;
+        }
+        HttpServletResponse response = (HttpServletResponse)servletResponse;
+        response.setHeader(TOKEN_KEY, token);
+        filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+}
--
libgit2 0.22.2