场景
根据自定义注解拦截请求,利用header的token机制从缓存中获取信息,实现参数注入,控制器Controller层自动获取用户信息
流程图
核心代码
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
boolean required() default true;
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UnAuthToken {
boolean required() default true;
}
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ApiIgnore
public @interface AuthUser {
/**
* 当前用户在request中的名字
*
* @return
*/
boolean value() default true;
}
/**
* 用户登录权限校验
*/
@Component
public class AuthUserInterceptor implements HandlerInterceptor {
private static Logger log = LoggerFactory.getLogger(AuthUserInterceptor.class);
@Autowired
UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!(handler instanceof HandlerMethod)) {
return true;
}
if (response.getStatus() == 404) {
throw new PathNotFoundException();
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
if (method.isAnnotationPresent(UnAuthToken.class)) {
return true;
}
// 如果不是映射到方法查看controller层注解
if (method.isAnnotationPresent(AuthToken.class) || handlerMethod.getBeanType().isAnnotationPresent(AuthToken.class)) {
//登录验证
AuthToken authToken = method.isAnnotationPresent(AuthToken.class) ? method.getAnnotation(AuthToken.class) : handlerMethod.getBeanType().getAnnotation(AuthToken.class);
if (authToken.required()) {
// 从 http 请求头中取出 token
String token = request.getHeader("token");
// token认证
if (null == token) {
throw new JWTVerificationException("token为空");
}
if (JWT.decode(token).getExpiresAt().compareTo(new Date()) < 0) {
throw new JWTVerificationException("token过期");
}
User user = userService.cacheUser(token);
TokenUtil.validateToken(user.getPassword(), token);
if(null == user){
throw new JWTVerificationException("账户已失效,请重新登录!");
}
log.warn("tokenExpires:" + DateUtil.toDate(JWT.decode(token).getExpiresAt(), "yyyy-MM-dd HH:mm:ss"));
}
}
return true;
}
}
/**
* 请求参数注解 @AuthUser user
*/
@Component
public class AuthUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(AuthUser.class)) {
return true;
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
if (parameter.hasParameterAnnotation(AuthUser.class)) {
return userService.cacheUser(webRequest.getHeader("token"));
}
}
}
@RestController
@RequestMapping("/api/area")
@Api(tags = "区域管理")
@AuthToken
public class AreaController {
@Autowired
private AreaService areaService;
@GetMapping("/list")
@ApiOperation("用户区域列表")
public JsonResult<List<Area>> list(@AuthUser User user) {
return JsonResult.success(areaService.getUserAreaList(user.getId()));
}
}