java接口调用过滤token

业务背景

处于对于安全需求,现需要将所有开放式接口(模板下载接口除外)转换为请求头Bear认证接口,因此需要在接口调用前加拦截器或者过滤器。

拦截器和过滤器

执行顺序:Request(请求)–>Filter(过滤器)–>Servlet(服务程序)–>Interceptor(拦截器)–>Controller(控制层)
可以理解为:

  • 过滤器是在请求进入Servlet之前,将不符合要求的请求过滤掉
  • 拦截器是在请求进入Servlet之后,将不符合的请求拦截,只返回部分预期的请求

过滤器和拦截器实际上基本相同,很多时候,过滤器与拦截器主要区别在于执行时机,根据不同业务的拦截时机来选择使用过滤器还是拦截器。

自定义过滤器实现

此篇文章使用过滤器进行token拦截过滤
自定义过滤器(代码):

/***************
 * 接口调用验证过滤器
 * @author zhou
 * @time 2024-01-02
 */
@Component
@Slf4j
public class TokenAuthorFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setContentType("text/plain;charset=UTF-8");

        String method = httpServletRequest.getMethod();
        //放行 options(嗅探) 请求
        if ("OPTIONS".equals(method)) {
            chain.doFilter(request, response);
            return; //跳过该嗅探请求
        }
        /*
            在SpringBoot中,ServletRequest和HttpServletRequest都是Java Web开发中的重要接口。
        ServletRequest是Java Web开发中定义的基本请求接口,它提供了获取请求参数、获取请求数据、获取客户端请求信息等方法。
        HttpServletRequest是ServletRequest的子类,它添加了一些处理HTTP协议相关的方法,如获取HTTP请求头、获取请求方式、获取会话信息等。
        */
        //1.获取请求url
        String url = httpServletRequest.getRequestURL().toString();
        //放行 模板下载请求
        if (url.contains("template") || url.contains("Template")) {
            chain.doFilter(request, response);
            return; //跳过该请求
        }
        if (url.contains("public-service")) {  // 拦截包含开放式接口请求路径的请求
            String bearer = httpServletRequest.getHeader("Bear");
            if (StringUtils.isEmpty(bearer)) {
                log.info("token不存在,返回未登录的信息");
                //因为没有在controller层,无法使用@RestController注解,需要自己将返回的数据转为JSON格式;
                String string = JSON.toJSONString(R.failed("登录信息不存在"));
                 /*
                 	getWriter() 是 httpServletResponse 接口的一个方法,它返回一个 PrintWriter 对象,用于将数据写入到响应输出流中。
                	write(string) 是 PrintWriter 对象的一个方法,用于将指定的字符串写入到响应输出流中。
                */
                httpServletResponse.getWriter().write(string); // 写入返回内容
                return;
            }
            // 使用redis进行token验证
            RedisUtils redisUtils = getBean(RedisUtils.class, httpServletRequest);
            String objects = (String) redisUtils.get("{pb" + bearer + "}"); // 自定义验证规则,与登录规则匹配
            if (StringUtils.isNotEmpty(objects)) {
                chain.doFilter(request, response);
            } else {
                String string = JSON.toJSONString(R.failed("验证信息不存在"));
                httpServletResponse.getWriter().write(string);
            }
        } else {
            chain.doFilter(request, response);
        }

    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    /**
     * 由于在过滤器中无法直接通过Autowired获取Bean,Bean还未自动注入,因此需要通过spring上下文来获取IOC管理的实体类
     * 此处主要是用于  RedisUserUtils
     *
     * @param clazz
     * @param request
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<T> clazz, HttpServletRequest request) {
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return applicationContext.getBean(clazz);
    }
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用拦截器(Interceptor)或过滤器(Filter)来实现在调用接口前和调用接口后的一些操作,比如检查token是否失效或过期,自动刷新token并存入Redis。 以下是一个基本的实现过程: 1. 编写拦截器或过滤器,在调用接口前和调用接口后进行操作。 2. 在调用接口前,从Redis中获取token,并检查token是否失效或过期。 3. 如果token失效或过期,则根据刷新token接口重新获取新的token,并将新的token存入Redis。 4. 在调用接口时,将新的token传递给接口。 下面是一个简单的实现示例: ```java public class TokenInterceptor implements HandlerInterceptor { @Autowired private RedisTemplate<String, String> redisTemplate; @Value("${token.expireTime}") private long expireTime; @Value("${token.refreshUrl}") private String refreshUrl; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 从请求头中获取token String token = request.getHeader("token"); if (StringUtils.isEmpty(token)) { throw new RuntimeException("token不能为空"); } // 从Redis中获取token对应的value值 String value = redisTemplate.opsForValue().get(token); if (StringUtils.isEmpty(value)) { throw new RuntimeException("token已失效,请重新登录"); } // 检查token是否过期 long expire = redisTemplate.getExpire(token, TimeUnit.SECONDS); if (expire <= 0) { // token已过期,重新获取并存入Redis String refreshedToken = refresh(token); redisTemplate.opsForValue().set(refreshedToken, value, expireTime, TimeUnit.SECONDS); redisTemplate.delete(token); // 将新的token传递给接口 request.setAttribute("token", refreshedToken); } else { // 将token传递给接口 request.setAttribute("token", token); } return true; } private String refresh(String token) { // 调用刷新token接口,获取新的token String refreshedToken = restTemplate.getForObject(refreshUrl + "?token=" + token, String.class); if (StringUtils.isEmpty(refreshedToken)) { throw new RuntimeException("刷新token失败"); } return refreshedToken; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // do nothing } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // do nothing } } ``` 在上面的代码中,我们定义了一个TokenInterceptor拦截器,并实现了preHandle方法,在该方法中进行了token的检查和刷新操作。 我们使用了Spring的RedisTemplate来操作Redis,其中expireTime和refreshUrl是从配置文件中读取的参数。如果token失效或过期,则调用refresh方法获取新的token,并将新的token存入Redis中,同时将新的token传递给接口。 我们还可以在配置文件中配置该拦截器: ```java @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private TokenInterceptor tokenInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor).addPathPatterns("/**"); } } ``` 这样,当我们调用接口时,TokenInterceptor拦截器会自动检查token并刷新token,确保我们的接口调用是有效的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值