Servlet API中提供了一个Filter接口 ,Filter接口在javax.servlet.Filter包下面。开发web应用时,如果编写的Java类实现了这个接口 ,则把这个java类称之为过滤器Filter 。
通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截 ,从而实现一些特殊的功能。
例如实现URL级别的权限访问控制、乱码问题 、过滤敏感词汇 、压缩响应信息 等一些高级功能。
filter在开发中的常见应用: 1.filter可以目标资源执行之前,进行权限检查,检查用户有无权限,如有权限则放行,如没有,则拒绝访问 2.filter可以放行之前,对request和response进行预处理,从而实现一些全局性的设置。 3.filter在放行之后,可以捕获到目标资源的输出,从而对输出作出类似于压缩这样的设置
在filter中可以对request请求进行拦截,并对response进行修改
实现Filter接口的话,需要重写3个方法init,doFilter和destroy
1 2 3 4 5 6 7 public interface Filter { void init(FilterConfig var1) throws ServletException; void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; void destroy(); }
而实现 OncePerRequestFilter 接口只用重写1个方法,其和 Filter 的区别参考:OncePerRequestFilter的作用
1 2 3 4 5 6 public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { } }
下面使用 OncePerRequestFilter 来实现一个java web token认证的功能
定义 JwtAuthenticationFilter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import lombok.extern.slf4j.Slf4j; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Slf4j public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { Cookie[] cookies = request.getCookies(); int len = cookies.length; for (int i = 0; i < len; i++) { Cookie cookie = cookies[i]; if ("token".equals(cookie.getName())) { log.info("has token"); break; } if (i == len - 1) { log.info("no token"); } } filterChain.doFilter(request, response); } }
配置filter,使该filter生效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import com.example.demo.jwt.JwtAuthenticationFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<JwtAuthenticationFilter> jwtFilter() { FilterRegistrationBean<JwtAuthenticationFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(new JwtAuthenticationFilter()); registration.addUrlPatterns("/*"); registration.setOrder(1); return registration; } }
3.请求接口,cookie中没有携带token的话,将会打印出no token
使用interceptor实现认证,参考:后端接口幂等性校验(数据库唯一索引 + 自定义注解和拦截器的token校验)
定义interceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j public class CheckTokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Cookie[] cookies = request.getCookies(); int len = cookies.length; for (int i = 0; i < len; i++) { Cookie cookie = cookies[i]; if ("token".equals(cookie.getName())) { log.info("has token"); break; } if (i == len - 1) { log.info("no token"); } } return true; // 是否放行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
配置config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import com.example.demo.jwt.CheckTokenInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class LoginConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 加载check token interceptor registry.addInterceptor(new CheckTokenInterceptor()) .addPathPatterns("/**"); // .excludePathPatterns("/admin") // .excludePathPatterns("/admin/login"); } }
3.请求接口,cookie中没有携带token的话,将会打印出no token
filter,interceptor和aop的区别参考:过滤器、拦截器和AOP的分析与对比