这里只供参考,比较使用jwt方式进行身份验证感觉不好,最不行的就是不能退出
登陆时设定多长过期时间,只能等这个时间过了以后才算退出,服务端只能验证请求过来的token是否通过验证
Code:
/** * Created by qhong on 2018/6/7 15:34 * 标注该注解的,就不需要登录 **/ @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AuthIgnore { }
LoginUser:
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface LoginUser { }
JwtUtil:
@ConfigurationProperties(prefix = "jwt") @Component public class JwtUtils { private Logger logger = LoggerFactory.getLogger(getClass()); private String secret; private long expire; private String header; /** * 生成jwt token */ public String generateToken(long userId) { Date nowDate = new Date(); //过期时间 Date expireDate = new Date(nowDate.getTime() + expire * 1000); return Jwts.builder() .setHeaderParam("typ", "JWT") .setSubject(userId+"") .setIssuedAt(nowDate) .setExpiration(expireDate) .signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, secret) .compact(); } public Claims getClaimByToken(String token) { try { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); }catch (Exception e){ logger.debug("validate is token error ", e); return null; } } /** * token是否过期 * @return true:过期 */ public boolean isTokenExpired(Date expiration) { return expiration.before(new Date()); } public String getSecret() { return secret; } public void setSecret(String secret) { this.secret = secret; } public long getExpire() { return expire; } public void setExpire(long expire) { this.expire = expire; } public String getHeader() { return header; } public void setHeader(String header) { this.header = header; } }
application.properties配置:
# 加密秘钥 jwt.secret=f4e2e52034348f86b67cde581c0f9eb5 # token有效时长,单位秒 jwt.expire=60000 jwt.header=token
拦截器:
/** * Created by qhong on 2018/6/7 15:36 **/ @Component public class AuthorizationInterceptor extends HandlerInterceptorAdapter { @Autowired private JwtUtils jwtUtils; public static final String USER_KEY = "userId"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { AuthIgnore annotation; if(handler instanceof HandlerMethod) { annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class); }else{ return true; } //如果有@AuthIgnore注解,则不验证token if(annotation != null){ return true; } //获取用户凭证 String token = request.getHeader(jwtUtils.getHeader()); if(StringUtils.isBlank(token)){ token = request.getParameter(jwtUtils.getHeader()); } //token凭证为空 if(StringUtils.isBlank(token)){ throw new AuthException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value()); } Claims claims = jwtUtils.getClaimByToken(token); if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){ throw new AuthException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value()); } //设置userId到request里,后续根据userId,获取用户信息 request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject())); return true; } }
注解拦截:
@Component public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Autowired private UserService userService; @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().isAssignableFrom(User.class) && parameter.hasParameterAnnotation(LoginUser.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container, NativeWebRequest request, WebDataBinderFactory factory) throws Exception { //获取用户ID Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST); if(object == null){ return null; } //获取用户信息 User user = userService.selectById((Long)object); return user; } }
WebConfig:
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private AuthorizationInterceptor authorizationInterceptor; @Autowired private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**"); } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(loginUserHandlerMethodArgumentResolver); } }
Login:
@PostMapping("/login") @AuthIgnore public R login2(@RequestBody User u){ //用户登录 long userId =userService.addUser(u); //生成token String token = jwtUtils.generateToken(userId); Map<String, Object> map = new HashMap<>(); map.put("token", token); map.put("expire", jwtUtils.getExpire()); return R.ok(map); }
LoginUser注解使用:
@RequestMapping(value="/query2",method= RequestMethod.POST) public User Query2(@LoginUser User u){ return u; }