這裏只供參考,比較使用jwt方式進行身份驗證感受很差,最不行的就是不能退出html
登錄時設定多長過時時間,只能等這個時間過了之後纔算退出,服務端只能驗證請求過來的token是否經過驗證git
Code:web
/** * Created by qhong on 2018/6/7 15:34 * 標註該註解的,就不須要登陸 **/ @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AuthIgnore { }
LoginUser:json
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface LoginUser { }
JwtUtil:app
@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配置:ide
# 加密祕鑰 jwt.secret=f4e2e52034348f86b67cde581c0f9eb5 # token有效時長,單位秒 jwt.expire=60000 jwt.header=token
攔截器:ui
/** * 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; } }
註解攔截:this
@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:spa
@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; }