guomengjiao 4 månader sedan
förälder
incheckning
5ca5d240c7

+ 7 - 8
ruoyi-api/src/main/java/com/ruoyi/api/controller/user/ApiUserLoginController.java

@@ -72,9 +72,8 @@ public class ApiUserLoginController extends AbstractApiController {
     @PostMapping("/user/authorization/login")
     public R<Map<String, Object>> loginAuthorization(@RequestBody  WxUserDto dto) {
         User user = userService.loginAuthorization(dto.getOpenId());
-        String token = apiTokenService.generateToken(user);
         HashMap<String, Object> result = new HashMap<>();
-        result.put("token", token);
+        result.put("token", loginSuccess(user, false, null, dto.getClientType()));
         return R.ok(result);
     }
 
@@ -99,7 +98,7 @@ public class ApiUserLoginController extends AbstractApiController {
         User user = userService.authorization(wxUserDto);
 
         HashMap<String, Object> result = new HashMap<>();
-        result.put("token", loginSuccess(user, true, null));
+        result.put("token", loginSuccess(user, true, null, wxUserDto.getClientType()));
         return R.ok(result);
     }
 
@@ -110,7 +109,7 @@ public class ApiUserLoginController extends AbstractApiController {
     @PostMapping("/captcha")
     public R<UserLoginVo> loginByCaptcha(@Validated @RequestBody UserLoginBo bo) {
         UserLoginVo userLoginVo = userService.loginByCaptcha(bo);
-        userLoginVo.setToken(loginSuccess(userLoginVo.getUser(), userLoginVo.getIsReg(), bo.getCid()));
+        userLoginVo.setToken(loginSuccess(userLoginVo.getUser(), userLoginVo.getIsReg(), bo.getCid(), bo.getClientType()));
         return R.ok(userLoginVo);
     }
 
@@ -121,7 +120,7 @@ public class ApiUserLoginController extends AbstractApiController {
     @PostMapping("/third")
     public R<UserLoginVo> loginByThird(@Validated @RequestBody ThirdLoginBo bo) {
         UserLoginVo userLoginVo = userService.loginByThird(bo);
-        userLoginVo.setToken(loginSuccess(userLoginVo.getUser(), false, bo.getCid()));
+        userLoginVo.setToken(loginSuccess(userLoginVo.getUser(), false, bo.getCid(), bo.getClientType()));
         return R.ok(userLoginVo);
     }
 
@@ -132,7 +131,7 @@ public class ApiUserLoginController extends AbstractApiController {
     @PostMapping("/third/register")
     public R<UserLoginVo> registerByThird(@Validated @RequestBody ThirdRegisterBo bo) {
         UserLoginVo userLoginVo = userService.registerByThird(bo);
-        userLoginVo.setToken(loginSuccess(userLoginVo.getUser(), userLoginVo.getIsReg(), bo.getCid()));
+        userLoginVo.setToken(loginSuccess(userLoginVo.getUser(), userLoginVo.getIsReg(), bo.getCid(), bo.getClientType()));
         return R.ok(userLoginVo);
     }
 
@@ -149,12 +148,12 @@ public class ApiUserLoginController extends AbstractApiController {
         return R.ok();
     }
 
-    private String loginSuccess(User user, Boolean isReg, String cid) {
+    private String loginSuccess(User user, Boolean isReg, String cid, Integer clientType) {
 //        //将unipush的客户端ID存入缓存
         log.info(String.format("个推客户端ID:%s", cid));
         if (StringUtils.isNotEmpty(cid)) {
             RedisUtils.setCacheObject(GeTuiUtils.getPushCid(String.valueOf(user.getId())), cid);
         }
-        return apiTokenService.generateToken(user);
+        return apiTokenService.generateToken(user, clientType);
     }
 }

+ 1 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -147,6 +147,7 @@ public interface Constants {
     public static final String REFRESH_TOKEN = "refresh_token";
 
     public static final String USER_ID = "user_id";
+    public static final String CLIENT_TYPE = "client_type";
 
     public static final String GAME_BONUS_POOL = "GAME_BONUS_POOL";
     /**

+ 5 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/LoginApiInterceptor.java

@@ -48,6 +48,10 @@ public class LoginApiInterceptor implements HandlerInterceptor {
 
             //通过jwt加密工具中自定义参数取出自己想要验证的值,来进行操作
             long tid = Long.parseLong(claims.get(Constants.USER_ID).toString());
+            Integer clientType = Integer.valueOf(claims.get(Constants.CLIENT_TYPE).toString());
+            if (!apiTokenService.validateToken(tid, clientType)) {
+                throw new ServiceException(ExceptionEnum.TOKEN_ERROR);
+            }
             User user = userService.getById(tid, false);
             if (ObjectUtil.isNull(user)) {
                 throw new ServiceException(ExceptionEnum.USER_NOT_EXISTS);
@@ -67,7 +71,7 @@ public class LoginApiInterceptor implements HandlerInterceptor {
 
             if (apiTokenService.isRefreshToken(expirationDateFromToken)) {
                 //刷新token,并返回
-                String token = apiTokenService.generateToken(user);
+                String token = apiTokenService.generateToken(user, clientType);
                 response.setHeader(Constants.REFRESH_TOKEN, token);
             }
 

+ 48 - 8
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ApiTokenService.java

@@ -7,7 +7,9 @@ import com.ruoyi.user.domain.User;
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Component;
 
 import java.util.Date;
@@ -35,10 +37,19 @@ public class ApiTokenService {
     @Value("${api-token.refreshTime}")
     private int refreshTime;
 
-    public String generateToken(User user) {
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    private static final String TOKEN_PREFIX = "token:";
+
+    public String generateToken(User user, Integer clientType) {
+        //先清掉token
+        clearOldTokens(user.getId(), clientType);
+
         Map<String, Object> claims = new HashMap<>();
         // 自定义参数,把需要存入token的参数都可以自定义到这里,比如 角色 部门类的关键参数
         claims.put(Constants.USER_ID, user.getId());
+        claims.put(Constants.CLIENT_TYPE, clientType);
         return doGenerateToken(claims, user.getNickname());
     }
 
@@ -56,13 +67,42 @@ public class ApiTokenService {
         System.out.println("当前时间+" + DateUtil.format(createdDate, DateUtils.YYYY_MM_DD_HH_MM_SS));
         System.out.println("过期时间+" + DateUtil.format(expirationDate, DateUtils.YYYY_MM_DD_HH_MM_SS));
 
-        return Jwts.builder()
-                .setClaims(claims) // 存入自定义参数
-                .setSubject(subject)
-                .setIssuedAt(createdDate)
-                .setExpiration(expirationDate)
-                .signWith(SignatureAlgorithm.HS512, secret)
-                .compact();
+        String token = Jwts.builder()
+            .setClaims(claims) // 存入自定义参数
+            .setSubject(subject)
+            .setIssuedAt(createdDate)
+            .setExpiration(expirationDate)
+            .signWith(SignatureAlgorithm.HS512, secret)
+            .compact();
+        storeToken(Long.parseLong(claims.get(Constants.USER_ID).toString()), Integer.valueOf(claims.get(Constants.CLIENT_TYPE).toString()), token);
+        return token;
+    }
+
+    public void storeToken(Long userId, Integer clientType, String token) {
+        String key = TOKEN_PREFIX + userId + ":" + clientType;
+        redisTemplate.opsForValue().set(key, token);
+    }
+
+    public void clearOldTokens(Long userId, Integer clientType) {
+        String pattern = TOKEN_PREFIX + userId + ":*";
+        redisTemplate.keys(pattern).forEach(key -> {
+            if (key.contains(clientType.toString())) {
+                redisTemplate.delete(key);
+            }
+        });
+    }
+
+    /**
+     * 验证token有效性
+     */
+    public boolean validateToken(Long userId, Integer clientType) {
+        try {
+            String key = TOKEN_PREFIX + userId + ":" + clientType;
+            // 检查token是否在活跃列表中
+            return redisTemplate.hasKey(key);
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     /**

+ 9 - 0
ruoyi-user/src/main/java/com/ruoyi/user/domain/bo/ThirdLoginBo.java

@@ -29,4 +29,13 @@ public class ThirdLoginBo implements Serializable {
      */
     @ApiModelProperty(value = "unipush的客户端ID")
     private String cid;
+
+    /**
+     * 1-商城小程序
+     * 2-微信支付小程序
+     * 3-支付宝支付小程序
+     * 4-app
+     */
+    @ApiModelProperty(value = "1-商城小程序 2-微信支付小程序 3-支付宝支付小程序 4-app")
+    private Integer clientType;
 }

+ 9 - 0
ruoyi-user/src/main/java/com/ruoyi/user/domain/bo/ThirdRegisterBo.java

@@ -43,4 +43,13 @@ public class ThirdRegisterBo implements Serializable {
      */
     @ApiModelProperty(value = "unipush的客户端ID")
     private String cid;
+
+    /**
+     * 1-商城小程序
+     * 2-微信支付小程序
+     * 3-支付宝支付小程序
+     * 4-app
+     */
+    @ApiModelProperty(value = "1-商城小程序 2-微信支付小程序 3-支付宝支付小程序 4-app")
+    private Integer clientType;
 }

+ 9 - 0
ruoyi-user/src/main/java/com/ruoyi/user/domain/bo/UserLoginBo.java

@@ -28,4 +28,13 @@ public class UserLoginBo implements Serializable {
      */
     @ApiModelProperty(value = "unipush的客户端ID")
     private String cid;
+
+    /**
+     * 1-商城小程序
+     * 2-微信支付小程序
+     * 3-支付宝支付小程序
+     * 4-app
+     */
+    @ApiModelProperty(value = "1-商城小程序 2-微信支付小程序 3-支付宝支付小程序 4-app")
+    private Integer clientType;
 }

+ 8 - 0
ruoyi-weixin/ruoyi-weixin-miniapp/src/main/java/com/ruoyi/weixin/domain/WxUserDto.java

@@ -69,4 +69,12 @@ public class WxUserDto implements Serializable {
      * 是否注册
      */
     private Boolean isReg = false;
+
+    /**
+     * 1-商城小程序
+     * 2-微信支付小程序
+     * 3-支付宝支付小程序
+     * 4-app
+     */
+    private Integer clientType;
 }