package com.ard.sample.component.websocket.config; import com.ard.common.constant.Constants; import com.ard.common.core.domain.model.LoginUser; import com.ard.framework.web.service.TokenService; import com.ard.sample.component.AuthInterceptor; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import lombok.extern.slf4j.Slf4j; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.support.DefaultHandshakeHandler; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.security.Principal; import java.util.Map; /** * @author sean.zhou * @date 2021/11/16 * @version 0.1 */ @Slf4j @Component public class AuthPrincipalHandler extends DefaultHandshakeHandler { @Resource private TokenService tokenService; @Override protected boolean isValidOrigin(ServerHttpRequest request) { if (request instanceof ServletServerHttpRequest) { HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest(); // 从请求参数获取 token(你也可以改成 header) String token = servletRequest.getParameter(AuthInterceptor.PARAM_TOKEN); if (!StringUtils.hasText(token)) { return false; } log.debug("websocket handshake token: {}", token); // 使用若依的 TokenService 校验 token 并获取用户 LoginUser loginUser = tokenService.getLoginUser(servletRequest); if (loginUser == null) { return false; } // 把 loginUser 放到 request,后面 determineUser 可以用 servletRequest.setAttribute(AuthInterceptor.TOKEN_CLAIM, loginUser); return true; } return false; } /** * The principal's name: {workspaceId}/{userType}/{userId} * @param request * @param wsHandler * @param attributes * @return */ @Override protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map attributes) { if (request instanceof ServletServerHttpRequest) { HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest(); LoginUser loginUser = (LoginUser) servletRequest.getAttribute(AuthInterceptor.TOKEN_CLAIM); if (loginUser != null) { // Principal 的名字可以自定义,这里用 userId/username return () -> loginUser.getUserId() + "/" + loginUser.getUsername(); } } return () -> null; } }