一、该问题的重现步骤是什么?
1. 设置服务端为登录有状态和单人登录模式,同时启动前端sword项目和saber项目
2. 选择chrome登录sword
3. 选择Firefox用相同账号登录saber
二、你期待的结果是什么?实际看到的又是什么?
期待sword项目登录的账号不会被顶掉,实际已经顶掉了
三、你正在使用的是什么产品,什么版本?在什么操作系统上?
商业版 2.6.0.RELEASE windows
四、请提供详细的错误堆栈信息,这很重要。
五、若有更多详细信息,请在下面提供。
blade.token.single配置成false
你好~
这样确实可以做到不同设备登录相同账号不会顶号,但是没法做到相同设备登录同一账号顶号这一目的
也就是我用Firefox和Chrome同时用同一账号登录Sword,没有顶号
以下是redis截图,两次登录产生了两个服务端状态,没有出现同设备同一个账号共用一个状态的情况
#blade配置 blade: #token配置 token: #是否有状态 state: true #单人登录模式 single: false # #令牌签名 # sign-key: BladeX
另外由于不是使用userId做redis的key,此时我也无法在登录时使用这个带两个参数的清除方法
#blade配置 blade: #token配置 token: #是否有状态 state: true #单人登录模式 single: false # #令牌签名 # sign-key: BladeX
清除掉其它的登录信息
已解决
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)