业务背景
处于对于安全需求,现需要将所有开放式接口(模板下载接口除外)转换为请求头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);
}
}