过滤器方式(不常用)
ServletConfig配置
@Configuration
@RequiredArgsConstructor
public class ServletConfig {
//redisTemplate
private final StringRedisTemplate redisTemplate;
/**
* @Author: pureyun
* @Data: 2024/6/29 16:52
* @Description: 配置原生filter,然后注册filter
* @param
* @return: org.springframework.boot.web.servlet.FilterRegistrationBean
**/
@Bean
public FilterRegistrationBean filterRegistrationBean(){
//创建FilterRegistrationBean的bean对象
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//创建自定义过滤器
LoginCheckFilter loginCheckFilter =new LoginCheckFilter(redisTemplate);
//将自定义的过滤器注册到FilterRegistrationBean中
filterRegistrationBean.setFilter(loginCheckFilter);
//给过滤器指定拦截的请求
//放行特定端口
// 拦截所有请求
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
Filter(参考模板)
public class LoginCheckFilter implements Filter {
private StringRedisTemplate redisTemplate;
public LoginCheckFilter(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
//过滤器拦截到请求的方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//先获得HttpServletRequest和HttpServletResponse
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//白名单通过
List<String> excludePath = new ArrayList<>();
excludePath.add("/login");
excludePath.add("/captcha/captchaImage");
String servletPath = request.getServletPath();
if (excludePath.contains(servletPath)) {
filterChain.doFilter(request,response);
return;
}
//其它请求都校验是否携带token,以及判断redis中是否存在token的键
String token = request.getHeader(WarehouseConstants.HEADER_TOKEN_NAME);
if (StringUtils.hasText(token) && redisTemplate.hasKey(token)) {
//如果 str 是 null,返回 false。
//如果 str 是空字符串(即长度为0),返回 false。
//如果 str 只包含空白字符(如空格、制表符等),返回 false。
//如果 str 包含至少一个非空白字符,返回 true。
filterChain.doFilter(request, response);
return;
}
//2没有,说明登录失败了
Result result =Result.err(Result.CODE_ERR_UNLOGINED,"您尚未登录");
String jsonString = JSON.toJSONString(result);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write(jsonString);
out.flush();
out.close();
}
}
拦截器方式(常用)
WebConfig
@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
private final LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器
registry.addInterceptor(loginCheckInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login","/captcha/captchaImage");
}
}
LoginCheckInterceptor
@Component
@RequiredArgsConstructor
public class LoginCheckInterceptor implements HandlerInterceptor {
private final StringRedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取token
String token = request.getHeader(WarehouseConstants.HEADER_TOKEN_NAME);
if(StringUtils.hasText(token)&&redisTemplate.hasKey(token)){
return true;
}
Result result = Result.err(Result.CODE_ERR_UNLOGINED,"没有权限访问");
String jsonString = JSON.toJSONString(result);//获取json字符串
response.setContentType("application/json;charset=utf-8");//设置返回类型
PrintWriter out = response.getWriter();
out.write(jsonString);
out.flush();
out.close();
return false;
}
}
小结
1.我们可以从中发现,用servlet原生的方式进行登录权限控制更加麻烦,但是拦截器就比较方便。
面试题
拦截器和过滤器区别?
直观回答:
1.过滤器可以修改request,而拦截器不能
2.过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
3.拦截器可以调用IOC容器中的各种依赖,而过滤器不能
4.过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
客观回答:
1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射
4、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
5、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。
6、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
————————————————
推荐原文链接:https://blog.csdn.net/weixin_44830949/article/details/127493342