websocket authentication @ServerEndpoint method

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class SimpleCORSFilter implements Filter {<!-- -->
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {<!-- -->
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {<!-- -->
        HttpServletRequest req= (HttpServletRequest) request;
        req.getSession().setAttribute("ipAddr",req.getRemoteHost());
        HttpServletResponse res = (HttpServletResponse)response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        res.setHeader("Access-Control-Max-Age", "3600");
        res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content- Type, X-E4M-With,userId,token,timestamp");
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {<!-- -->
    }
}
import com.neo.websocket.WebSocketConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;


@Component
@ServerEndpoint(value = "/wsTask/{userId}/{tId}", configurator = WebSocketConfig.class) //Interface path ws://localhost:8087/webSocket/userId/111;
public class TaskWebSocket {<!-- -->
    private static AsynSendMsg asyncSendMsg;

    @Autowired
    public void setAsynSendMsg(AsynSendMsg asyncSendMsg) {<!-- -->
        TaskWebSocket.asyncSendMsg = asyncSendMsg;
    }

    public Logger log = LogManager.getLogger(getClass());

    //The connection session with a client needs to be used to send data to the client
    private Session session;
    /**
     *User ID
     */
    private String userId;

    //The thread-safe Set of the concurrent package is used to store the MyWebSocket object corresponding to each client.
    //Although @Component is singleton mode by default, springboot will still initialize a bean for each websocket connection, so it can be saved with a static set.
    // Note: WebSocket below is the current class name
    private static CopyOnWriteArraySet<TaskWebSocket> webSockets =new CopyOnWriteArraySet<>();
    // Used to store user information for line connection
    private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();


    public Session getSession() {<!-- -->
        return session;
    }

    public String getUserId() {<!-- -->
        return userId;
    }

    public static CopyOnWriteArraySet<TaskWebSocket> getWebSockets() {<!-- -->
        return webSockets;
    }

    public static ConcurrentHashMap<String, Session> getSessionPool() {<!-- -->
        return sessionPool;
    }

    /**
     * Method called successfully by link
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value="userId")String userId, @PathParam(value="tId")String tId) {<!-- -->
        try {<!-- -->
            this.session = session;
            this.userId = userId;
            webSockets.add(this);
            sessionPool.put(userId, session);
            log.info("[websocket message] There are new connections, the total number is:" + webSockets.size());
            asyncSendMsg.sendOneMessage(userId,tId,session);
        } catch (Exception e) {<!-- -->
        }
    }

    /**
     * Method called by link closing
     */
    @OnClose
    public void onClose() {<!-- -->
        try {<!-- -->
            webSockets.remove(this);
            sessionPool.remove(this.userId);
            log.info("[websocket message] The connection is disconnected, the total number is:" + webSockets.size());
        } catch (Exception e) {<!-- -->
        }
    }
    /**
     * Method called after receiving client message
     *
     * @param message
     */
    @OnMessage
    public void onMessage(String message) throws InterruptedException {<!-- -->
        log.info("[websocket message] Received client message:" + message);
    }

    /** Handling when sending errors
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {<!-- -->
        log.error("User error, reason:" + error.getMessage());
        error.printStackTrace();
    }


    // This is a broadcast message
    public void sendAllMessage(String message) {<!-- -->
        log.info("[websocket message] broadcast message:" + message);
        for(TaskWebSocket webSocket : webSockets) {<!-- -->
            try {<!-- -->
                if(webSocket.session.isOpen()) {<!-- -->
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {<!-- -->
                e.printStackTrace();
            }
        }
    }

    // This is a single point message
    public void sendOneMessage(String userId,String message,Session session) throws InterruptedException {<!-- -->

        while (sessionPool.get(userId)!= null & amp; & amp;sessionPool.get(userId).isOpen()) {<!-- -->
            try {<!-- -->
                log.info("[websocket message] Single point message:" + message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {<!-- -->
                e.printStackTrace();
            }
            Thread.sleep(2000);
        }
    }

    // This is a single point message (multiple people)
    public void sendMoreMessage(String[] userIds, String message) {<!-- -->
        for(String userId:userIds) {<!-- -->
            Session session = sessionPool.get(userId);
            if (session != null & amp; & amp;session.isOpen()) {<!-- -->
                try {<!-- -->
                    log.info("[websocket message] Single point message:" + message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {<!-- -->
                    e.printStackTrace();
                }
            }
        }

    }

}


import com.alibaba.fastjson.JSONObject;
import com.neo.dao.UserInfoDao;
import com.neo.utils.IpUtils;
import com.neo.utils.JwtUtils;
import com.neo.utils.SpringUtils;
import io.jsonwebtoken.ExpiredJwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import java.util.List;


//When packaging and deploying to tomcat, annotations are required
@Component
@Configuration
@WebListener
public class WebSocketConfig extends ServerEndpointConfig.Configurator {<!-- -->
    public Logger logger = LoggerFactory.getLogger(getClass());
@Bean
    public ServerEndpointExporter serverEndpointExporter()
    {<!-- -->
        return new ServerEndpointExporter();
    }
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {<!-- -->
        //Get request headers
        List<String> list = request.getHeaders().get("Sec-WebSocket-Protocol");

        //When the Sec-WebSocket-Protocol request header is not empty, the same response needs to be returned to the front end
        response.getHeaders().put("Sec-WebSocket-Protocol",list);
        if(list == null ||list.size()==0) {<!-- -->
            throw new RuntimeException("No token parameter");
        }else {<!-- -->
            for (String token : list) {<!-- -->
                Boolean verfy = JwtUtils.verfy(token);
                if(!verfy) {<!-- -->
                    logger.info("token is invalid");
                    throw new RuntimeException("token is invalid");
                }else {<!-- -->
                    try {<!-- -->
                        HttpSession session = (HttpSession) request.getHttpSession();
                        String addr = "";
                        if (session != null) {<!-- -->
                            addr = session.getAttribute("ipAddr").toString();
                        }
                        String subject = JwtUtils.parseJwt(token).getSubject();
                        JSONObject jsonObject = JSONObject.parseObject(subject);
                        String ip = jsonObject.getString("ip");
                        String fingerprintToken = jsonObject.getString("fingerprint");
                        String userAgent = request.getHeaders().get("User-Agent").get(0);
                        String fingerprint = userAgent;
                        if (!ip.equals(addr) || !fingerprintToken.contains(fingerprint)) {<!-- -->
                            logger.info("The network environment has changed, please log in again!");
                            throw new RuntimeException("The network environment has changed, please log in again!");
                        } else {<!-- -->
                            UserInfoDao userInfoDao = SpringUtils.getBean("userInfoDao", UserInfoDao.class);
                            int i = userInfoDao.countToken(token);
                            if (i > 0) {<!-- -->
                                super.modifyHandshake(sec, request, response);
                            } else {<!-- -->
                                logger.info("Token has expired, please log in again!");
                                throw new RuntimeException("Token has expired, please log in again!");
                            }
                        }
                    } catch (ExpiredJwtException e) {<!-- -->
                        logger.info("token has expired");
                        throw new RuntimeException("token has expired");
                    } catch (Exception e) {<!-- -->
                        logger.info("token has expired");
                        e.printStackTrace();
                        throw new RuntimeException("token has expired");
                    }
                }
            }
        }
    }
}