OncePerRequestFilter 是一个过滤器,每个请求都会执行一次;一般开发中主要是做检查是否已登录、Token是否过期和授权等操作,而每个操作都是一个过滤器,下面演示一下。
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 检查是否登录过期 * * @author francis * @create: 2023-08-30 16:45 **/ @Component @Slf4j public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { log.info("进入 JwtAuthenticationTokenFilter ..."); /** * 从 request 的 header 中拿出来 token */ String token = request.getHeader("token"); if (token == null || token.isEmpty()) { // 没有携带 token 则 放行 filterChain.doFilter(request, response); return; } /** * 检查 token 是否过期逻辑 ..... */ // 放行 filterChain.doFilter(request, response); } }
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 请求日志 * * @author francis * @create: 2023-08-31 10:15 **/ @Component @Slf4j public class OperationLogFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { log.info("OperationLogFilter ..."); /** * 操作日志记录 ... */ // 放行 filterChain.doFilter(request, response); } }
import com.security.filter.JwtAuthenticationTokenFilter; import com.security.filter.OperationLogFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; /** * Security 配置类 * * @author francis * @create: 2023-08-30 14:19 **/ @Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; @Autowired private OperationLogFilter operationLogFilter; @Override protected void configure(HttpSecurity http) throws Exception { http // 关闭csrf .csrf().disable() // 不通过 Session 获取 SecurityContext .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() // 对于登录接口 允许匿名访问 .antMatchers("/login") .permitAll() // 除上面外的所有请求全部需要鉴权认证 .anyRequest() .authenticated(); // 在 UsernamePasswordAuthenticationFilter(验证用户) 之前执行 // TODO 需要注意的是下面过滤器的顺序就是执行的顺序,使用 @Order 也没办法改变 http // 登录是否过期 .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) // 请求日志 .addFilterBefore(operationLogFilter, UsernamePasswordAuthenticationFilter.class); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }