- 登录接口返回token
- 请求携带header里token验证登录状态
- redis 返回登录时间
上代码:
yml配置:
##前端登录配置
session:
config:
##是否启用
enable: true
##携带key
headerKey: api-token
##拦截路径逗号分割
patterns: /shop/me/**,/me/**
##session超时配置
hourTimeOut: 24
config类
@Data
@Component
public class SessionConfig {
@Value("${session.config.hourTimeOut:24}")
private Integer hourTimeOut;
@Value("${session.config.enable:true}")
private Boolean enable;
@Value("${session.config.patterns:/**}")
private String patterns;
@Value("${session.config.headerKey:api-token}")
private String headerKey;
}
用户上下文
public class LoginUserContext implements Serializable {
private static ThreadLocal<LoginUserInfo> threadLocal =
new ThreadLocal<>();
public static LoginUserInfo getUserSession() {
return threadLocal.get();
}
public static void setUserSession(LoginUserInfo entity) {
threadLocal.set(entity);
}
public static void removeUserSession() {
threadLocal.remove();
}
}
用户登录
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class LoginUserInfo implements java.io.Serializable {
private Long userId;
private String userName;
private String sessionKey;
}
常量
public class GlobalConstant {
public static final String SESSION_TOKEN = "lg:token:%s";
public static final String SESSION_USER_TOKEN = "lg:user:token:%d";
}
spring拦截器配置
@Slf4j
@Configuration
public class SessionWebConfig implements WebMvcConfigurer {
@Autowired
private SessionConfig sessionConfig;
@Autowired
private SessionInterceptor sessionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> pathPatterns = Arrays.asList(sessionConfig.getPatterns().split(","));
List<String> excludePathPatterns = Lists.newArrayList("/doc.html/**", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
log.info("-----------auth session interceptor patterns-------------");
log.info("------pathPatterns-----{}", JSON.toJSONString(pathPatterns));
log.info("------excludePathPatterns-----{}", JSON.toJSONString(excludePathPatterns));
registry.addInterceptor(sessionInterceptor)
.addPathPatterns(pathPatterns)
.excludePathPatterns(excludePathPatterns);
}
}
不需要登录得方法注解
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface NotAuth {
}
拦截器代码
@Slf4j
@Component
public class SessionInterceptor extends HandlerInterceptorAdapter {
@Autowired
private SessionConfig sessionConfig;
@Resource
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
LoginUserContext.removeUserSession();
if (!sessionConfig.getEnable()) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 配置该注解,说明不进行服务拦截
NotAuth notAuth = handlerMethod.getBeanType().getAnnotation(NotAuth.class);
if (notAuth != null) {
return true;
}
String token = request.getHeader(sessionConfig.getHeaderKey());
LoginUserInfo loginUserInfo = null;
if (StringUtils.isNotEmpty(token)) {
loginUserInfo =
(LoginUserInfo) this.redisTemplate.opsForValue().get(
SessionKeyUtil.getRedisToken(token)
);
}
if (loginUserInfo == null) {
log.error("not login token {} method {} ", token, handlerMethod.getMethod().getName());
throw new RongTongCodeException(401, "未登录");
}
LoginUserContext.setUserSession(loginUserInfo);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LoginUserContext.removeUserSession();
}
}
登录rpc
@Component
public class UserLoginRpc {
@Resource
private RedisTemplate redisTemplate;
@Autowired
private SessionConfig sessionConfig;
/**
* 登录接口
*
* @param loginUserInfo
* @return
*/
public String login(LoginUserInfo loginUserInfo) {
if (loginUserInfo == null || loginUserInfo.getUserId() == null) {
throw new RongTongCodeException(400, "登录用户参数异常");
}
//上个登录token有效期5分钟
String userToken = SessionKeyUtil.getRedisUserToken(loginUserInfo.getUserId());
String alreadyLogin = (String) this.redisTemplate.opsForValue().get(userToken);
if (StringUtils.isNotEmpty(alreadyLogin)) {
//已经登录的token 5分钟
this.redisTemplate.expire(
SessionKeyUtil.getRedisToken(alreadyLogin),
5,
TimeUnit.MINUTES
);
}
this.redisTemplate.delete(userToken);
return this.setSession(loginUserInfo);
}
private String setSession(LoginUserInfo loginUserInfo) {
String token = java.util.UUID.randomUUID().toString()
.replaceAll("-", "");
this.redisTemplate.opsForValue().set(
SessionKeyUtil.getRedisToken(token), loginUserInfo
, sessionConfig.getHourTimeOut(), TimeUnit.HOURS
);
this.redisTemplate.opsForValue().set(
SessionKeyUtil.getRedisUserToken(loginUserInfo.getUserId()), token
, sessionConfig.getHourTimeOut(), TimeUnit.HOURS
);
return token;
}
}