一、该问题的重现步骤是什么?
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,此时我也无法在登录时使用这个带两个参数的清除方法
JwtUtil.removeAccessToken(userInfo.getUser().getTenantId(), String.valueOf(userInfo.getUser().getId()));
清除掉其它的登录信息
已解决
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;
以上方式解决~