package com.ruoyi.web.webSocket;
|
|
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.core.domain.model.LoginUserApplet;
|
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.system.model.TAppUser;
|
import com.ruoyi.system.service.TAppUserService;
|
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Jwts;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.StringUtils;
|
|
import java.util.Map;
|
|
/**
|
* WebSocket认证处理器
|
* 处理WebSocket连接的用户认证逻辑
|
*/
|
@Component
|
@Slf4j
|
public class WebSocketAuthHandler {
|
|
@Autowired
|
private TAppUserService appUserService;
|
|
@Autowired
|
private RedisCache redisCache;
|
|
// 令牌秘钥
|
@Value("${token.secret}")
|
private String secret;
|
|
/**
|
* 验证用户认证信息
|
* @param appUserId 用户ID
|
* @param token 认证令牌(可选)
|
* @return 认证结果
|
*/
|
public AuthResult authenticateUser(String appUserId, String token) {
|
try {
|
if (appUserId == null || appUserId.trim().isEmpty()) {
|
return AuthResult.failure("用户ID不能为空");
|
}
|
|
// 查询用户信息
|
TAppUser appUser = appUserService.getById(appUserId);
|
if (appUser == null) {
|
return AuthResult.failure("用户不存在");
|
}
|
|
// 检查用户状态
|
if (appUser.getStatus() == null || appUser.getStatus() != 1) {
|
return AuthResult.failure("用户已被禁用");
|
}
|
|
// 检查用户审核状态
|
if (appUser.getState() == null || appUser.getState() != 1) {
|
return AuthResult.failure("用户未通过审核");
|
}
|
|
// 这里可以添加token验证逻辑
|
if (token != null && !token.trim().isEmpty()) {
|
// 验证token的有效性
|
if (!validateToken(appUserId, token)) {
|
return AuthResult.failure("认证令牌无效");
|
}
|
}
|
|
return AuthResult.success(appUser);
|
} catch (Exception e) {
|
log.error("用户认证失败,用户ID: {}, 错误: {}", appUserId, e.getMessage(), e);
|
return AuthResult.failure("认证过程中发生错误: " + e.getMessage());
|
}
|
}
|
|
/**
|
* 验证token
|
* @param appUserId 用户ID
|
* @param token 令牌
|
* @return 是否有效
|
*/
|
private boolean validateToken(String appUserId, String token) {
|
try {
|
if (!StringUtils.hasText(token)) {
|
log.debug("用户 {} 未提供token,跳过token验证", appUserId);
|
return true; // 如果没有提供token,允许通过(可以根据业务需求调整)
|
}
|
|
// 移除Bearer前缀
|
if (token.startsWith(Constants.TOKEN_PREFIX)) {
|
token = token.replace(Constants.TOKEN_PREFIX, "");
|
}
|
|
// 解析JWT token
|
Claims claims = parseToken(token);
|
if (claims == null) {
|
log.warn("用户 {} 的token解析失败", appUserId);
|
return false;
|
}
|
|
// 从token中获取用户标识
|
String uuid = (String) claims.get(Constants.LOGIN_USER_APPLET_KEY);
|
if (!StringUtils.hasText(uuid)) {
|
log.warn("用户 {} 的token中未找到用户标识", appUserId);
|
return false;
|
}
|
|
// 从Redis中获取用户登录信息
|
String userKey = getTokenKey(uuid);
|
LoginUserApplet loginUser = redisCache.getCacheObject(userKey);
|
|
if (loginUser == null) {
|
log.warn("用户 {} 的登录信息已过期或不存在", appUserId);
|
return false;
|
}
|
|
// 验证用户ID是否匹配
|
if (!appUserId.equals(loginUser.getUserId())) {
|
log.warn("用户 {} 的token与提供的用户ID不匹配", appUserId);
|
return false;
|
}
|
|
// 验证token是否过期
|
long currentTime = System.currentTimeMillis();
|
if (loginUser.getExpireTime() != null && loginUser.getExpireTime() < currentTime) {
|
log.warn("用户 {} 的token已过期", appUserId);
|
return false;
|
}
|
|
log.debug("用户 {} 的token验证成功", appUserId);
|
return true;
|
|
} catch (Exception e) {
|
log.error("验证用户 {} 的token时发生错误: {}", appUserId, e.getMessage(), e);
|
return false;
|
}
|
}
|
|
/**
|
* 解析JWT token
|
* @param token JWT token
|
* @return Claims对象
|
*/
|
private Claims parseToken(String token) {
|
try {
|
return Jwts.parser()
|
.setSigningKey(secret)
|
.parseClaimsJws(token)
|
.getBody();
|
} catch (Exception e) {
|
log.error("解析token失败: {}", e.getMessage());
|
return null;
|
}
|
}
|
|
/**
|
* 获取token在Redis中的key
|
* @param uuid 用户唯一标识
|
* @return Redis key
|
*/
|
private String getTokenKey(String uuid) {
|
return com.ruoyi.common.constant.CacheConstants.LOGIN_TOKEN_KEY + uuid;
|
}
|
|
/**
|
* 认证结果类
|
*/
|
public static class AuthResult {
|
private final boolean success;
|
private final String message;
|
private final TAppUser appUser;
|
|
private AuthResult(boolean success, String message, TAppUser appUser) {
|
this.success = success;
|
this.message = message;
|
this.appUser = appUser;
|
}
|
|
public static AuthResult success(TAppUser appUser) {
|
return new AuthResult(true, "认证成功", appUser);
|
}
|
|
public static AuthResult failure(String message) {
|
return new AuthResult(false, message, null);
|
}
|
|
public boolean isSuccess() {
|
return success;
|
}
|
|
public String getMessage() {
|
return message;
|
}
|
|
public TAppUser getAppUser() {
|
return appUser;
|
}
|
}
|
|
/**
|
* 从认证消息中提取用户信息
|
* @param messageObj 消息对象
|
* @return 用户认证信息
|
*/
|
public UserAuthInfo extractAuthInfo(Map<String, Object> messageObj) {
|
String appUserId = (String) messageObj.get("appUserId");
|
String token = (String) messageObj.get("token");
|
String deviceId = (String) messageObj.get("deviceId");
|
String deviceType = (String) messageObj.get("deviceType");
|
|
return new UserAuthInfo(appUserId, token, deviceId, deviceType);
|
}
|
|
/**
|
* 用户认证信息类
|
*/
|
public static class UserAuthInfo {
|
private final String appUserId;
|
private final String token;
|
private final String deviceId;
|
private final String deviceType;
|
|
public UserAuthInfo(String appUserId, String token, String deviceId, String deviceType) {
|
this.appUserId = appUserId;
|
this.token = token;
|
this.deviceId = deviceId;
|
this.deviceType = deviceType;
|
}
|
|
public String getAppUserId() {
|
return appUserId;
|
}
|
|
public String getToken() {
|
return token;
|
}
|
|
public String getDeviceId() {
|
return deviceId;
|
}
|
|
public String getDeviceType() {
|
return deviceType;
|
}
|
}
|
}
|