tonglin0325的个人主页

SpringBoot学习笔记——filter和interceptor

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认证的功能

  1. 定义 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);
}
}

  1. 配置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校验)

  1. 定义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 {

}

}

  1. 配置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的分析与对比