|
|
|
@ -0,0 +1,266 @@ |
|
|
|
package com.ruoyi.applet.utils; |
|
|
|
|
|
|
|
import com.ruoyi.common.constant.Constants; |
|
|
|
import com.ruoyi.common.core.domain.model.LoginApplet; |
|
|
|
import com.ruoyi.common.core.redis.RedisCache; |
|
|
|
import com.ruoyi.common.exception.ServiceException; |
|
|
|
import com.ruoyi.common.utils.ServletUtils; |
|
|
|
import com.ruoyi.common.utils.StringUtils; |
|
|
|
import com.ruoyi.common.utils.spring.SpringUtils; |
|
|
|
import com.ruoyi.model.domain.AppUsers; |
|
|
|
import com.ruoyi.model.service.IAppUsersService; |
|
|
|
import io.jsonwebtoken.Claims; |
|
|
|
import io.jsonwebtoken.Jwts; |
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
import org.springframework.http.HttpStatus; |
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
|
|
|
|
/** |
|
|
|
* 伴宠师小程序Token解析工具类 |
|
|
|
* 提供从HTTP请求头中获取token并解析成伴宠师用户信息的功能 |
|
|
|
* |
|
|
|
* @author ruoyi |
|
|
|
*/ |
|
|
|
@Component |
|
|
|
public class AppletTokenUtils { |
|
|
|
|
|
|
|
// 令牌自定义标识 |
|
|
|
@Value("${token.header}") |
|
|
|
private String header; |
|
|
|
|
|
|
|
// 令牌秘钥 |
|
|
|
@Value("${token.secret}") |
|
|
|
private String secret; |
|
|
|
|
|
|
|
private static RedisCache redisCache; |
|
|
|
|
|
|
|
private static IAppUsersService appUsersService; |
|
|
|
|
|
|
|
static { |
|
|
|
redisCache = SpringUtils.getBean(RedisCache.class); |
|
|
|
appUsersService = SpringUtils.getBean(IAppUsersService.class); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从当前HTTP请求中获取伴宠师用户ID |
|
|
|
* 这是最常用的方法,用于获取当前登录的伴宠师用户ID |
|
|
|
* |
|
|
|
* @return 伴宠师用户ID,如果未登录或token无效则返回null |
|
|
|
*/ |
|
|
|
public static Long getCurrentAppletUserId() { |
|
|
|
try { |
|
|
|
LoginApplet loginApplet = getCurrentLoginApplet(); |
|
|
|
return loginApplet != null ? loginApplet.getAppletId() : null; |
|
|
|
} catch (Exception e) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从当前HTTP请求中获取伴宠师用户ID(强制要求) |
|
|
|
* 如果获取失败会抛出异常 |
|
|
|
* |
|
|
|
* @return 伴宠师用户ID |
|
|
|
* @throws ServiceException 当获取失败时抛出 |
|
|
|
*/ |
|
|
|
public static Long requireCurrentAppletUserId() { |
|
|
|
Long userId = getCurrentAppletUserId(); |
|
|
|
if (userId == null) { |
|
|
|
throw new ServiceException("请先登录", HttpStatus.UNAUTHORIZED.value()); |
|
|
|
} |
|
|
|
AppUsers users = appUsersService.getById(userId); |
|
|
|
if (users == null) { |
|
|
|
throw new ServiceException("请重新登录", HttpStatus.UNAUTHORIZED.value()); |
|
|
|
} |
|
|
|
return userId; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从当前HTTP请求中获取伴宠师登录信息 |
|
|
|
* |
|
|
|
* @return LoginApplet对象,包含用户ID、token、登录时间等信息 |
|
|
|
*/ |
|
|
|
public static LoginApplet getCurrentLoginApplet() { |
|
|
|
try { |
|
|
|
HttpServletRequest request = ServletUtils.getRequest(); |
|
|
|
return getLoginAppletFromRequest(request); |
|
|
|
} catch (Exception e) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从指定的HTTP请求中获取伴宠师登录信息 |
|
|
|
* |
|
|
|
* @param request HTTP请求对象 |
|
|
|
* @return LoginApplet对象 |
|
|
|
*/ |
|
|
|
public static LoginApplet getLoginAppletFromRequest(HttpServletRequest request) { |
|
|
|
if (request == null) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
// 获取请求携带的令牌 |
|
|
|
String token = extractTokenFromRequest(request); |
|
|
|
if (StringUtils.isEmpty(token)) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
AppletTokenUtils instance = SpringUtils.getBean(AppletTokenUtils.class); |
|
|
|
Claims claims = instance.parseToken(token); |
|
|
|
|
|
|
|
// 解析对应的权限以及用户信息 |
|
|
|
String uuid = (String) claims.get(Constants.LOGIN_APPLET_KEY); |
|
|
|
if (StringUtils.isEmpty(uuid)) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
String userKey = Constants.LOGIN_APPLET_TOKEN_KEY + uuid; |
|
|
|
return redisCache.getCacheObject(userKey); |
|
|
|
} catch (Exception e) { |
|
|
|
// 记录日志但不抛出异常,返回null让调用方处理 |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 验证当前请求是否包含有效的伴宠师token |
|
|
|
* |
|
|
|
* @return true表示有效,false表示无效 |
|
|
|
*/ |
|
|
|
public static boolean hasValidAppletToken() { |
|
|
|
try { |
|
|
|
LoginApplet loginApplet = getCurrentLoginApplet(); |
|
|
|
return loginApplet != null && loginApplet.getAppletId() != null; |
|
|
|
} catch (Exception e) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 验证指定请求是否包含有效的伴宠师token |
|
|
|
* |
|
|
|
* @param request HTTP请求对象 |
|
|
|
* @return true表示有效,false表示无效 |
|
|
|
*/ |
|
|
|
public static boolean hasValidAppletToken(HttpServletRequest request) { |
|
|
|
try { |
|
|
|
LoginApplet loginApplet = getLoginAppletFromRequest(request); |
|
|
|
return loginApplet != null && loginApplet.getAppletId() != null; |
|
|
|
} catch (Exception e) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从HTTP请求中提取token字符串 |
|
|
|
* |
|
|
|
* @param request HTTP请求对象 |
|
|
|
* @return token字符串,如果不存在则返回null |
|
|
|
*/ |
|
|
|
private static String extractTokenFromRequest(HttpServletRequest request) { |
|
|
|
try { |
|
|
|
AppletTokenUtils instance = SpringUtils.getBean(AppletTokenUtils.class); |
|
|
|
String token = request.getHeader(instance.header); |
|
|
|
if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { |
|
|
|
token = token.replace(Constants.TOKEN_PREFIX, ""); |
|
|
|
} |
|
|
|
return token; |
|
|
|
} catch (Exception e) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从令牌中获取数据声明 |
|
|
|
* |
|
|
|
* @param token 令牌 |
|
|
|
* @return 数据声明 |
|
|
|
* @throws Exception 解析失败时抛出 |
|
|
|
*/ |
|
|
|
private Claims parseToken(String token) throws Exception { |
|
|
|
return Jwts.parser() |
|
|
|
.setSigningKey(secret) |
|
|
|
.parseClaimsJws(token) |
|
|
|
.getBody(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 检查当前用户是否为指定用户 |
|
|
|
* |
|
|
|
* @param userId 要检查的用户ID |
|
|
|
* @return true表示是当前用户,false表示不是 |
|
|
|
*/ |
|
|
|
public static boolean isCurrentUser(Long userId) { |
|
|
|
if (userId == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
Long currentUserId = getCurrentAppletUserId(); |
|
|
|
return userId.equals(currentUserId); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 要求当前请求必须包含有效的伴宠师token,否则抛出异常 |
|
|
|
* |
|
|
|
* @throws ServiceException 当token无效时抛出 |
|
|
|
*/ |
|
|
|
public static void requireValidAppletToken() { |
|
|
|
if (!hasValidAppletToken()) { |
|
|
|
throw new ServiceException("请先登录", HttpStatus.UNAUTHORIZED.value()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 要求当前用户必须是指定用户,否则抛出异常 |
|
|
|
* |
|
|
|
* @param userId 要求的用户ID |
|
|
|
* @throws ServiceException 当用户不匹配时抛出 |
|
|
|
*/ |
|
|
|
public static void requireCurrentUser(Long userId) { |
|
|
|
requireValidAppletToken(); |
|
|
|
if (!isCurrentUser(userId)) { |
|
|
|
throw new ServiceException("无权限访问", HttpStatus.FORBIDDEN.value()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取当前登录用户的token字符串 |
|
|
|
* |
|
|
|
* @return token字符串,如果未登录则返回null |
|
|
|
*/ |
|
|
|
public static String getCurrentToken() { |
|
|
|
try { |
|
|
|
HttpServletRequest request = ServletUtils.getRequest(); |
|
|
|
return extractTokenFromRequest(request); |
|
|
|
} catch (Exception e) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 检查token是否即将过期(剩余时间少于指定分钟数) |
|
|
|
* |
|
|
|
* @param minutes 检查的分钟数阈值 |
|
|
|
* @return true表示即将过期,false表示还有足够时间 |
|
|
|
*/ |
|
|
|
public static boolean isTokenExpiringSoon(int minutes) { |
|
|
|
try { |
|
|
|
LoginApplet loginApplet = getCurrentLoginApplet(); |
|
|
|
if (loginApplet == null || loginApplet.getExpireTime() == null) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
long currentTime = System.currentTimeMillis(); |
|
|
|
long expireTime = loginApplet.getExpireTime(); |
|
|
|
long remainingTime = expireTime - currentTime; |
|
|
|
long thresholdTime = minutes * 60 * 1000L; // 转换为毫秒 |
|
|
|
|
|
|
|
return remainingTime < thresholdTime; |
|
|
|
} catch (Exception e) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |