Java拦截所有接口请求并过滤请求头内容

我这里使用的是SpringBoot工程,例子是一个登陆拦截请求头得例子。

例子中所用到的依赖:(自行根据需要添加)


        
            cn.hutool
            hutool-all
            5.5.2
        

            
                com.alibaba
                fastjson
                ${fastjson.version}
            
            
            
                org.projectlombok
                lombok
                ${lombok.version}
            

自定义的返回格式:

/**
 * 通用返回值
 * @param 
 */
@Data
public class Result {

    //返回码
    private Integer code;

    //返回消息
    private String message;

    //返回数据
    private T data;

    // 私有化构造,无参构造
    private Result() {}

    // 返回数据 有参构造
    public static  Result build(T body, Integer code, String message) {
        Result result = new Result<>();
        result.setData(body);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

}

按步骤来,直接可用版!

话不多说直接上代码!

1.创建自定义拦截器,用于拦截接口请求,获取请求头的token,并放到本地线程中。token是登陆成功后放到redis里的,下面我会说

/**
 * 自定义拦截器
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 在所有操纵之前执行
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求方式,如果是options(预检请求)直接放行
        String method = request.getMethod();
        if ("OPTIONS".equals(method)){
            return true;//如果是预检请求 直接放行
        }
        //2.从请求头获取token值,我这里把token放请求头了
        String token = request.getHeader("token");
        if (StrUtil.isEmpty(token)){
            responseNoLoginInfo(response);//返回505友好提示
            return false;
        }
        //3.拿获取到的token查询redis
        String userInfo = redisTemplate.opsForValue().get("user:token" + token);
        if (StrUtil.isEmpty(userInfo)){
            responseNoLoginInfo(response);
            return false;
        }
        //4.讲查询到的用户信息放到ThreadLocal线程中
        ThreadLocalUtils.set(JSON.parseObject(userInfo, User.class));
        //5.将redis用户过期时间更新,保证操作能正常完成
        redisTemplate.expire("user:token"+token,30, TimeUnit.MINUTES);
        //5.放行
        return true;
    }

    /**
     * 返回响应状态码 505
     * @param response
     */
    private void responseNoLoginInfo(HttpServletResponse response) {
        Result result = Result.build(null,505,"");
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(JSON.toJSONString(result));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) writer.close();
        }
    }

    /**
     * 在所有操作之后执行
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        //删除本地线程ThreadLocal
        ThreadLocalUtils.remove();
    }
}

2.ThreadLocal工具类,用于添加、获取、删除token信息

public class ThreadLocalUtils{
    //1.创建ThreadLocal线程对象
    public static final ThreadLocal threadLocal = new ThreadLocal<>();

    /**
     * 添加数据的方法
     * @param User
     */
    public static void set(User user) {
        threadLocal.set(user);
    }

    /**
     * 获取数据的方法
     */
    public static User get() {
        return threadLocal.get();
    }

    /**
     * 删除数据的方法
     */
    public static void remove() {
        threadLocal.remove();
    }
}

3.User类

@Data
public class User {

	private String userName;

	private String password;


}

4.MVC拦截器配置类

@Component
public class MvcConfig implements WebMvcConfigurer {
    //注册拦截器
    @Autowired
    private LoginInterceptor loginInterceptor;
  

    /**
     * MVC解决跨域
     * @param registry
     * 我在这里直接解决跨域了,不然每个接口都要加注解   
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")//添加规则路径
                .allowCredentials(true)//允许跨域情况下传递cookie
                .allowedOriginPatterns("*")//允许所有请求
                .allowedMethods("*")//允许请求得方法
                .allowedHeaders("*");//允许得请求头
    }
    /**
     * 注册自定义拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)//添加自定义拦截器
               .excludePathPatterns("/login")//白名单路径,可添加多个用 用 "",隔开
                .addPathPatterns("/**");//拦截所有
    }
}

5.登陆接口、和获取用户信息接口

@RestController
public class Test{
//注入redis
 @Autowired
 private RedisTemplate redisTemplate;
    /**
     * 获取当前登陆用户信息
     */
    @GetMapping("/getUserInfo")
    public Result getUserInfo(){
        //使用ThreadLocal后可以从拦截器获取token
        return Result.build(AuthContextUtil.get(),200,"请求成功!");
    }
    /**
     * 用户登录
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestBody User user){
        //获取用户名和密码
        String userName = user.getUserName();
        String password = user.getPassword();
        //这里不做过多处理,直接生成token存redis
        User user=new User();
         user.setUserName(userName );
        user.setPassword(password);
        //这里token我用UUID
        String token = UUID.randomUUID().toString().replaceAll("-", "");
                   //存redis,key:token value:字符串类型user对象  redisTemplate.opsForValue().set("user:token"+token,JSON.toJSONString(user),1, TimeUnit.DAYS);
        return Result.build(user,200,"请求成功!");
    }
}

测试自行测试,就不给例子了

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