自定义全局拦截器

配置拦截器

我们通过实现WebMvcConfigurer的addInterceptors方法来增加自定义拦截器

InterceptorConfig.java

import com.wwk.xinyao.common.intecepter.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;

/**
 * Description: 配置所有拦截器类
 * Author  wwk
 * Date    2023/7/11 15:36
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    
    @Resource
    private LoginInterceptor loginInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(loginInterceptor).addPathPatterns("/chatApi/test");
    }
}

实现拦截需要验证登录态的Api

​ 首先我们需要考虑哪些Api需要认证登录态才可以访问,比如获取用户的个人信息,假设我们没有做拦截器,来来接这一类的Api那么所有人都可通过它来取到任何一个用户的用户信息,这个就完全没有了安全性.

​ 所以我们需要增加这样的拦截器来控制我们到底需要对外暴露哪些Api提供给用户使用,哪些Api是需要认证之后才能提供给用户的

​ 有了上面的拦截器的配置其实,其实实现起来不困难了,我们首先要知道拦截器就是,当我请求一个Api的地址之后,拦截器就会根据地址来判断是否需要拦截,假设地址是需要拦截的,就会进入拦截器先进行判断能都通过,通过了在放开,如果没有通过,用户就得不到想要的数据

自定义验证登录态拦截器

  1. 我们首先需要注册一个自定义的拦截器来来接指定地址的请求

InterceptorConfig.java

// 注册loginInterceptor拦截器,拦截'/chatApi/test'URI的请求
registry.addInterceptor(loginInterceptor).addPathPatterns("/chatApi/test");

  1. 我们需要给拦截器增加判断条件

LoginInterceptor

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.wwk.xinyao.chat.annotation.PrivateApi;
import com.wwk.xinyao.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 登录验证拦截器
 * Author  wwk
 * Date    2023/7/11 15:38
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    
    

    private  static final String AUTH_TOKEN_HEADER = "X-Auth-Token";
    @Resource
    private UserService userService;

    @Value("${xy.http.header-token-prefix}")
    private String tokenPrefix; ;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        //获取用户传来的token信息,通过请求头
        if(isPrivateApi(handler)){
    
     //是私有的需要验证登录态
            String token = getToken(request);
            Long uid = userService.checkLogin(token);
            return !Objects.isNull(uid);
        }
        return true;
    }

    /**
     * 根据注解来判api是不是私有的,如果是就需要认证登录态
     * @return 是否不是私有的
     */
    private boolean isPrivateApi(Object handler){
    
    
        if(handler instanceof HandlerMethod){
    
    
            HandlerMethod handlerMethod= (HandlerMethod) handler;
            PrivateApi methodAnnotation = handlerMethod.getMethodAnnotation(PrivateApi.class);
            return methodAnnotation != null;
        }
        throw new IllegalStateException("Not supported for handler "+handler);
    }


    /**
     * 获取前段传来的封装好的token
     * @param request Http请求
     * @return 真正的token token?token:null
     */
    private String getToken(HttpServletRequest request){
    
    
        String safeToken = request.getHeader(AUTH_TOKEN_HEADER);
        if(StringUtils.isNotBlank(safeToken)){
    
    
            return safeToken.split(" ")[1];
        }
        return null;
    }
}

注意:这里我们可以看出,前端会通过请求头携带token的方式把封装好的token发送给后端进行校验,当后端进入到拦截器之后,首先我们会去判断这个Api是否是私有的,也就是不允许被访问的,如果它是私有的我们就需要通过一些手段来验证用户是否可以访问这个Api,当然这个拦截器里我们验证的是用户的登录态,如果是私有的,我们就需要先去验证登录态,通过了在执行api的方法,不通过就直接拦截,如果不是私有的就直接放行

通过自定注解来判断Api是都是私有的

这里我的做法是自定义个注解,可以通过给Api加上指定的注解来判断,Api的私有性

  1. 创建自定义注解

com/wwk/xinyao/chat/annotation/PrivateApi.java

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 是否是私有的Api(如果是就要验证登录态)
 * Author  wwk
 * Date    2023/7/11 16:13
 */
@Target({
    
    METHOD})
@Retention(RUNTIME)
public @interface PrivateApi {
    
    
     boolean value() default true;
}

  1. 给方法上增加注解
@GetMapping("/test")
@PrivateApi // 代表api是私有的,不写注解就是公共的
public String test(){
    
    
  System.out.println("123");
  return "ok";
}

猜你喜欢

转载自blog.csdn.net/m0_59757074/article/details/131697301