这里只供参考,比较使用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 * ); 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=
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;
}