Springboot添加登陆拦截
1)引入jwt(Json web token (JWT))
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
2) 添加自定义annotation,方便设定哪些method需要token验证,哪些不需要
创建PassToken.java
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean required() default true;
}
创建UserLoginToken.java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
3) 创建类,实现 HandlerInterceptor,主要是 preHandle 函数
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private HitsMapper hitsMapper;
@Autowired
private userServiceImp userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");//从request里面拿token
if(!(handler instanceof HandlerMethod)){// 如果不是method,直接放行
return true;
}
if(handler instanceof ResourceHttpRequestHandler){// 如果是资源类请求,直接放行
return true;
}
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
if(method.isAnnotationPresent(PassToken.class)){// 如果方法上有注释PassToken,跳过登陆验证
PassToken pstoken = method.getAnnotation(PassToken.class);
if(pstoken.required()){
return true;
}
}
if(method.isAnnotationPresent(UserLoginToken.class)){//如果方法上有注释UserLoginToken,进行登陆验证
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if(userLoginToken.required()){
if (token == null) {
throw new RuntimeException("无token,请重新登录");// response.status=500
}
String email="";
try{
email= JWT.decode(token).getAudience().get(0);
}catch (JWTDecodeException j){
throw new RuntimeException("token不正确");// response.status=500
}
System.out.println(email);
User user = userService.findUserByEmail(email);
// User user = hitsMapper.getUserByEmail(email);
if (user == null) {
throw new RuntimeException("用户不存在,请重新登录");// response.status=500
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new RuntimeException("token不合法");// response.status=500
}
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
4) APi中使用方法:登陆验证为例
@ApiOperation(value="check user by email",notes = "通过用户登陆信息返回token")
@RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
@PassToken
public Response<String> checkLogin(
@ApiParam(value = "user info") @RequestBody User user ) throws JSONException {
String email = user.getEmail();
String passWord = user.getPassword();
User user1 = hitsMapper.getUserByEmail(email);
if(user1==null){
return Response.fail(405,"登录失败,用户不存在");
}else{
if(!user1.getPassword().equals(passWord)){
return Response.fail(406,"登录失败,密码错误");
}else{
String token = tokenService.getToken(user1);
return Response.success(token);// code=200, message="success"
}
}
}
6) tokenService中生成token
@Service
public class tokenService {
public String getToken(User user) {
String token="";
// 根据email和password生成token
token= JWT.create().withAudience(user.getEmail())
.sign(Algorithm.HMAC256(user.getPassword()));
return token;
}
}
踩坑:HandlerInterceptor的实现类里面的@Autowired注入的是null,如上述AuthenticationInterceptor类里面的hitsMapper和userService是null,
原因:
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
// 拦截所有请求
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/index.html","/","/user/login","/css/*","/js/*","/images/*","/swagger-ui.html","/**/*.html","/**/*.css","/**/*.js");
}//这里authenticationInterceptor()如果改成new AuthenticationInterceptor()的话,注入就会失败,并且需要将上述HandlerInterceptor的实现类AuthenticationInterceptor在此配置类中加上bean
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
参考:https://www.jianshu.com/p/e88d3f8151db

浙公网安备 33010602011771号