1. 首先创建一个拦截器类
前端代码:
axios.post(
serverUrl + '/userInfo/my?userId=' + userInfo.id,
userInfoMore,
{
headers: {
'headerUserId': userInfo.id,
'headerUserToken': userInfo.userUniqueToken
}
})
后端代码:
public class UserTokenInterceptor implements HandlerInterceptor {
// redis中存储token的key
public static final String USER_REDIS_TOKEN = "user_redis_token";
@Autowired
private RedisOperator redisOperator;
/**
* 拦截请求,在访问controller调用之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取前端传入的 headerUserId、headerUserToken
String userId = request.getHeader("headerUserId");
String userToken = request.getHeader("headerUserToken");
if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)) {
// 从redis中获取 当前userId对应的token
String uniqueToken = redisOperator.get(USER_REDIS_TOKEN + ":" + userId);
if (StringUtils.isNotBlank(uniqueToken)) {
// 将 redis 中的 token 和前端传入的 token 作对比,如果一致,说明用户的登录信息校验通过
if(uniqueToken.equals(userToken)){
return true;
}else {
// 前后端的token不一致,说明账号有可能在其他地方再次登录,从而生成了一个新的token
returnInterceptorInfo(response, DIDIOKJSONResult.errorMsg("账号异地登录"));
}
}else {
// redis中不存在该用户userId对应的token,说明该用户没有登录(因为token是在登录时生成的,没有token就说明没登录过)
returnInterceptorInfo(response, DIDIOKJSONResult.errorMsg("请登录"));
}
}else {
// 前端传入的信息为空,说明前端没有用户的登录信息
returnInterceptorInfo(response, DIDIOKJSONResult.errorMsg("请登录"));
}
/**
* false: 请求被拦截,被驳回,验证出现问题
* true: 请求在经过验证校验以后,是OK的,是可以放行的
*/
return false;
}
/**
* 组装用户请求被拦截的响应信息
* @param response
* @param result
*/
private void returnInterceptorInfo(HttpServletResponse response, DIDIOKJSONResult result){
OutputStream out = null;
try {
response.setCharacterEncoding("utf-8");
response.setContentType("text/json");
out = response.getOutputStream();
out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 请求访问controller之后,渲染视图之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 请求访问controller之后,渲染视图之后
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
2. 将拦截器类注册到Spring容器中
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public UserTokenInterceptor userTokenInterceptor(){
return new UserTokenInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userTokenInterceptor())
.addPathPatterns("/userInfo/*") // 需要经过拦截器的 路由地址
.excludePathPatterns("/userInfo/blog"); // 不需要经过拦截器的路由地址
WebMvcConfigurer.super.addInterceptors(registry);
}
}
3. 测试
然后刷新用户信息试一下,(调用接口:/userInfo/my?userId=123)
客户端会提示:请登录。说明进入拦截器了!