请问登录时如何做到按设备进行顶号?

Blade 未结 2 1199
mnxm
mnxm 剑童 2020-10-18 12:23
悬赏:5

一、该问题的重现步骤是什么?

1. 设置服务端为登录有状态和单人登录模式,同时启动前端sword项目和saber项目

2. 选择chrome登录sword

3. 选择Firefox用相同账号登录saber


二、你期待的结果是什么?实际看到的又是什么?

期待sword项目登录的账号不会被顶掉,实际已经顶掉了


三、你正在使用的是什么产品,什么版本?在什么操作系统上?

商业版 2.6.0.RELEASE windows


四、请提供详细的错误堆栈信息,这很重要。


五、若有更多详细信息,请在下面提供。

2条回答
  • blade.token.single配置成false

    U`OPNDKF2MK8)@]_71$D]3Y.png

    KESX0V1ALHTLRQ$EPO~7U%K.png

    作者追问:2020-10-19 12:40

    你好~

    这样确实可以做到不同设备登录相同账号不会顶号,但是没法做到相同设备登录同一账号顶号这一目的

    也就是我用Firefox和Chrome同时用同一账号登录Sword,没有顶号

    以下是redis截图,两次登录产生了两个服务端状态,没有出现同设备同一个账号共用一个状态的情况

    image.png


    #blade配置
    blade:
      #token配置
      token:
        #是否有状态
        state: true
        #单人登录模式
        single: false
    #    #令牌签名
    #    sign-key: BladeX


    作者追问:2020-10-19 12:49

    另外由于不是使用userId做redis的key,此时我也无法在登录时使用这个带两个参数的清除方法

    JwtUtil.removeAccessToken(userInfo.getUser().getTenantId(), String.valueOf(userInfo.getUser().getId()));

    清除掉其它的登录信息

    0 讨论(0)
  • 2020-10-22 14:31

    已解决


    BladeConfiguration中添加配置

    /**
     * 接口验证配置
     * @return
     */
    @Bean
    public ISecureHandler secureHandler() {
       return new ExSecureHandlerHandler();
    }

    ExSecureHandlerHandler类

    /**
     * @author xxx
     */
    public class ExSecureHandlerHandler extends SecureHandlerHandler {
    
       /**
        * token验证
        * @return
        */
       @Override
       public HandlerInterceptorAdapter tokenInterceptor() {
          return new ExTokenInterceptor();
       }
    }

    ExTokenInterceptor类

    /**
     * @author xxx
     */
    public class ExTokenInterceptor extends TokenInterceptor {
    
       private static final Logger log = LoggerFactory.getLogger(TokenInterceptor.class);
    
       /**
        * 按设备顶号
        * @param request
        * @param response
        * @param handler
        * @return
        */
       @Override
       public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
          BladeUser user = AuthUtil.getUser();
          String accessToken = CommonUtil.getAccessToken(user.getTenantId(), user.getClientId(), String.valueOf(user.getUserId()));
          String currentAccessToken = JwtUtil.getToken(WebUtil.getRequest().getHeader(TokenConstant.HEADER));
    
          if (null == user || !accessToken.equals(currentAccessToken)) {
             log.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}", new Object[]{request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap())});
             ResponseProvider.write(response);
             return false;
          } else {
             return true;
          }
       }
    }
    /**
     * 通用工具类
     *
     * @author Chill
     */
    public class CommonUtil {
    
       /**
        * 获取AccessToken
        * @param tenantId
        * @param clientId
        * @param userId
        * @return
        */
       public static String getAccessToken(String tenantId, String clientId, String userId) {
          RedisTemplate<String, Object> redisTemplate = JwtUtil.getRedisTemplate();
          return String.valueOf(redisTemplate.opsForValue().get(getAccessTokenKey(tenantId, clientId, userId)));
       }
    
       /**
        * 设置AccessToken
        * @param tenantId
        * @param clientId
        * @param userId
        * @param accessToken
        */
       public static void addAccessToken(String tenantId, String clientId, String userId, String accessToken) {
          RedisTemplate<String, Object> redisTemplate = JwtUtil.getRedisTemplate();
          redisTemplate.opsForValue().set(getAccessTokenKey(tenantId, clientId, userId), accessToken, 3600, TimeUnit.SECONDS);
       }
    
       /**
        * 获取AccessToken的key
        * @param tenantId
        * @param clientId
        * @param userId
        * @return
        */
       public static String getAccessTokenKey(String tenantId, String clientId, String userId) {
          return tenantId.concat(":blade:token:").concat(clientId).concat(":").concat(userId);
       }
    }


    最后登录中修改(/oauth/token)

    Kv result = TokenUtil.createAuthInfo(userInfo);
    User user = userInfo.getUser();
    CommonUtil.addAccessToken(user.getTenantId(), SecureUtil.getClientIdFromHeader(), String.valueOf(user.getId()), String.valueOf(result.get(TokenConstant.ACCESS_TOKEN)));
    
    return result;


    以上方式解决~

    0 讨论(0)
提交回复