hutool工具使用进行token验证,解析token,

时间:2024-11-11 06:59:00

前端部分:封装了axios进行请求拦截

class Http {
  service: any;
  constructor(config: TOption) {
    //实例化请求配置
    this.service = axios.create(config);
    //请求拦截  Authorization自定义名字
    this.service.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        loading = ElLoading.service({ fullscreen: true,text:'加载中...' });
        console.log(token.value);
        if (token.value) {
          (config.headers as AxiosRequestHeaders).Authorization = token.value;
        }
        return config;
      },
      (error: any) => {
        loading.close();
        return Promise.reject(error);
      }
    );

完整代码:

import axios, {
  AxiosRequestConfig,
  AxiosRequestHeaders,
  AxiosResponse,
} from "axios";
import { ElMessage, ElLoading } from "element-plus";
import { storeToRefs } from "pinia";
import appStore from "@/store/appStore";
let {  token } = storeToRefs(appStore());

const state = {
  ok: 0,//请求成功状态码
  401:"ERR_BAD_REQUEST"
};

//返回数据规则
interface IResponseData<T> {
  status: number;
  message?: string;
  data: T;
  code: string;
}

//请求默认配置规则
type TOption = {
  baseURL: string;
  timeout: number;
};

//默认配置
const config = {
  baseURL: "",
  timeout: 30 * 1000,
  withCredentials: true,
};


let loading:any = null;

class Http {
  service: any;
  constructor(config: TOption) {
    //实例化请求配置
    this.service = axios.create(config);

    //请求拦截  Authorization自定义名字
    this.service.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        loading = ElLoading.service({ fullscreen: true,text:'加载中...' });
        console.log(token.value);
        if (token.value) {
          (config.headers as AxiosRequestHeaders).Authorization = token.value;
        }
        return config;
      },
      (error: any) => {
        loading.close();
        return Promise.reject(error);
      }
    );

    //响应拦截
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        loading.close();

        const data = response.data;
      
        const { code } = data;
  
        if (code == undefined) {
          //如果没有返回状态码,直接返回数据,针对于返回数据为blob类型    
          return response;
        } else if (code !== 0) {
          ElMessage.error(data.message);
          return Promise.reject(data);
        }
        // code == 0 的时候,提取我们只关注的Api数据data
        return response.data.data;
      },
      (error: any) => {
        loading.close();
     
        if(error.code==state[401]){
          ElMessage.error("请求失败:"+error.message);

          setTimeout(() => {
            localStorage.removeItem('com.beiyou')
            window.location.href = '/#/login'
          },1000);
        }
        return Promise.reject(error);
      }
    );
  }

  get<T>(url: string, params?: object, data = {}): Promise<IResponseData<T>> {
    return this.service.get(url, { params, ...data });
  }

  post<T>(url: string, params?: object, data = {}): Promise<IResponseData<T>> {
    return this.service.post(url, params, data);
  }

  put<T>(url: string, params?: object, data = {}): Promise<IResponseData<T>> {
    return this.service.put(url, params, data);
  }

  delete<T>(
    url: string,
    params?: object,
    data = {}
  ): Promise<IResponseData<T>> {
    return this.service.delete(url, { params, ...data });
  }
}

export default new Http(config);

后端进行验证
首先自定义注解排除token校验注解类
为不需要校验 token 的方法定义注解
@Documented //标记注解
@Target() //指定作用在方法上 对方法拦截
@Retention() //作用域 在运行时有效

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NoAuthorization {
    String value() default "";
}

自定义的token秘钥

 = great123

编写拦截器token验证的拦截器
1.实现HandlerInterceptor接口重写preHandle方法
2.获取正在运行的方法上面,是否有@NoAuthorization注解,如果有就结束执行,不拦截,不校验token
3.获取前端传来的token,如果有就进行验证,没有就直接抛出401交给前端处理

import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWTUtil;
import com.beimao.annotation.NoAuthorization;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
public class TokenInterceptor implements HandlerInterceptor {

    //由于注册器那边是new的新对象,所以拦截器这边不能注册到IOC容器里面
    //这边采用构造方法的形式传参给注册器,由注册器注入到IOC容器里面
    private String tokenKey;

    public TokenInterceptor(String tokenKey) {
        this.tokenKey = tokenKey;
    }

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {
            //handler是object类型不能直接调用,如果不强转可以用反射().getMethod()
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //判断有没有注解
            NoAuthorization noAuthorization = handlerMethod.getMethod().getAnnotation(NoAuthorization.class);
            if (noAuthorization != null) {
                //如果有该注解,证明该方法不需要token验证;
                return true;
            }
           }

        //获取token 前端起的名字Authorization
        String token = request.getHeader("Authorization");

        //如果token不为空,进行token验证
        if (StrUtil.isNotEmpty(token)) {
            // 证token   verify(toen,秘钥.getBytes) hu-tool工具类  返回布尔类型  验证内容是否相当和是否过期
            boolean pass = JWTUtil.verify(token, tokenKey.getBytes());

            if (pass == false) {
                //验证失败,返回401
                response.setStatus(401);
                return false;
            } else {
              //解析token
                JWT jwt = JWTUtil.parseToken(token);

                return true;
            }
        }

        //没有token,直接返回401
        response.setStatus(401);
        return false;

    }
}

最后进行token拦截器注册

import com.beimao.interceptor.TokenInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Value("${}")
    private String tokenKey;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        TokenInterceptor loginInterceptor = new TokenInterceptor(tokenKey);
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/api/**"); //拦截请求的url前缀
        //.excludePathPatterns("/css/**","/images/**","/js/**");// 放行
    }
}