基于springboot+vue项目配置JWT

首先引入pom依赖 

        
            com.auth0
            java-jwt
            3.10.3
        

添加拦截器配置类 

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor())
                .addPathPatterns("/**") //拦截所有请求 通过判断token是否合法是否需要登录
                .excludePathPatterns("/user/login","/user/register","/**/import","/**/export"); //需要排除的 URL 路径模式的参数,使用它可以指定哪些 URL 不应该被拦截器拦截。
    }
    @Bean
    public JwtInterceptor jwtInterceptor () {
        return new JwtInterceptor();
    }
}

 

 创建JwtUtil 工具类,生成Token  这里类的注解可以不用@Service 换成@Component 大致功能是相同的 都是将类注入IOC容器中进行管理

@Service
public class JwtUtil {

    private static UserService staticuserService;
    @Resource
    private UserService userService;

    //将动态的 userService 引入 静态方法  方便静态查询当前userToken方法
    @PostConstruct
    public void setUserService(){
        staticuserService = userService;
    }
    /**
     * 生成token
     */
    public static String createToken(User user) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7); //默认令牌过期时间7天
        JWTCreator.Builder builder = JWT.create();
        return builder.withClaim("userid",String.valueOf(user.getUserid()))
//给builder 添加令牌
        .withExpiresAt(calendar.getTime())
//                以password作为密钥 通过HMAC256算法进行加密
                .sign(Algorithm.HMAC256(user.getPassword()));
    }

    public static User getCurrentUser(){
        try {
//            RequestContextHolder顾名思义,持有上下文的Request容器
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String token = request.getHeader("token");
            if (StrUtil.isNotBlank(token)){
                String userid = JWT.decode(token).getClaim("userid").asString();
                return staticuserService.getById(Integer.parseInt(userid));
            }
        }catch (Exception e) {
//            获取数据异常
            throw new ServiceException(DATA_ERROR);
        }
        return null;
    }
}

axios请求接口的js文件设置请求头中的token (不必写在实例里面)

// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8';
    
    let user = localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")):{}
    if (user){
        config.headers['token'] = user.token;  // 设置请求头
    }
    
    return config
}, error => {
    return Promise.reject(error)
});

 然后检验发送的请求中 Header是否具有token

基于springboot+vue项目配置JWT_第1张图片

 通过拦截器的preHandle方法拦截登录的请求头 获取token。此处的ServiceException见我主页的我的自定义异常类

public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  {
        String token = request.getHeader("Token");
        if (!(handler instanceof HandlerMethod)){
            return true;
        }
//        获取失败 token不存在
        if (StrUtil.isBlank(token)){
            throw new ServiceException(TOKEN_NOT_EXIST);
        }
/**
 * 本处有逻辑错误:通过token寻找userid 若token修改则无法找到User(实际User存在) 控制台报错 220 用户不存在
 */
        String userid;
        try {
//            在TokenUtils中 用withClaim将token存放至本地存储
            userid = JWT.decode(token).getClaim("userid").asString();
        }catch (JWTDecodeException j){
            throw new ServiceException(TOKEN_ERROR);
        }

//        根据token查询数据库进行对比
        User user = userService.getById(Integer.parseInt(userid));
        if (user == null) {
            throw new ServiceException(ACCOUNT_NOT_EXIST);
        }

//        验证用户密码加签验证token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try{
            jwtVerifier.verify(token);
        }catch (JWTVerificationException e){
            throw new ServiceException(ACCOUNT_NOT_EXIST);
        }
        return true;
    }
}

在login登录实现类下 将token存储在userDto里,通过UserDto类与页面进行数据传输回显

@Override
    public UserDto login(UserDto userDto) {
//        通过dto获取的数据查询对应的User
        User one = getUserInfo(userDto);
        if (one != null){
//        然后将User的数据传到userDto
            BeanUtils.copyProperties(one,userDto);
            String token = JwtUtil.createToken(one);
            userDto.setToken(token);
            return userDto;
        }else {
            throw new ServiceException(LOGIN_MOBLE_ERROR);
        }
    }

此时在控制台则能发现token生成成功。 

基于springboot+vue项目配置JWT_第2张图片

 最后在自己的请求登录的接口下面

 将自己的user信息存放在本地存储空间

基于springboot+vue项目配置JWT_第3张图片

 通过前端的接口拦截器,判断截取的状态码进行提示错误信息

// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
    response => {
        let res = response.data;
        // 如果是返回的文件
        if (response.config.responseType === 'blob') {
            return res
        }
        // 兼容服务端返回的字符串数据
        if (typeof res === 'string') {
            res = res ? JSON.parse(res) : res
        }
        // 当验证不通过
        if (res.code == '220') {
            ElementUI.Message({
                message : res.message,
                type : 'error'
            })
        }
        return res;
    },

 就实现JWT啦!

你可能感兴趣的:(spring,boot,java,spring)