2021.01.12 Springboot 使用JWT 生成token

梗概:

JWT意思是Json web token,通过POST参数或者在HTTP header发送,然后进行验证,验证通过之后,就能返回响应的资源给浏览器。

1、引入依赖:


      com.auth0
      java-jwt
      3.4.0

2、自定义两个注解

2.1 用来跳过验证的PassToken

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
    boolean required() default true;
}

2.2 需要登录才能进行操作的注解UserLoginToken

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
    boolean required() default true;
}

3、 封装生成Token的工具类

public class JWTUtils {
    public static String getToken(String userId, String mobile) {
        return JWT.create()
                .withAudience(userId)
                .sign(Algorithm.HMAC256(mobile));
    }
}

4、新增一个拦截器AuthenticationInterceptor

package com.ruoyi.framework.interceptor;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.ruoyi.common.exception.AppUserLoginException;
import com.ruoyi.system.domain.TAppUser;
import com.ruoyi.system.mapper.TAppUserMapper;
import com.ruoyi.system.service.ITAppUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author 蔡志健
 * @date 2021/1/7 22:18
 **/
public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
    private TAppUserMapper tAppUserMapper;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //检查是否有passtoken注释,有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (token == null) {
                    throw new AppUserLoginException("无token,请重新登录");
                }
                // 获取 token 中的 user id
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new AppUserLoginException("token验证失败");
                }
                TAppUser user = tAppUserMapper.selectTAppUserByUserId(userId);
                if (user == null) {
                    throw new AppUserLoginException("用户不存在,请重新登录");
                }
                // 验证 token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getMobile())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new AppUserLoginException("token验证失败");
                }
                return true;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) {
    }

}

备注:

  • TAppUserMapper 对应自己的Mapper
  • AppUserLoginException是自己封装的异常类

5、配置拦截器

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");   
    }
    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

6、验证
不加注解的话默认不验证,登录接口一般是不验证的。在getMessage()中我加上了登录注解,说明该接口必须登录获取token后,在请求头中加上token并通过验证才可以访问

6.1 不进行token验证

 @RequestMapping("/login")
    public AjaxResult loginByCode(@RequestParam("mobile") String mobile, @RequestParam("code") String code) {
                ...业务逻辑...
        return AjaxResult.success("success", tAppUser);
    }

6.2 进行token验证

    @UserLoginToken
    @RequestMapping("/info")
    public AjaxResult selectTAppUserByUserId(@RequestParam("userId") String userId) {
        return itAppUserService.selectTAppUserByUserId(userId);
    }

请求示例:

2021.01.12 Springboot 使用JWT 生成token_第1张图片
header中放进token

你可能感兴趣的:(2021.01.12 Springboot 使用JWT 生成token)