Spring Security之默认的过滤器链及自定义Filter操作
过滤器顺序从上到下
自定义 Filter自定义的 Filter 建议继承 GenericFilterBean,本文示例:
package com.example.filter;import org.springframework.web.filter.GenericFilterBean;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;/** * @author 咸鱼 * @date 2019-05-26 18:02 */public class BeforeLoginFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println('在 UsernamePasswordAuthenticationFilter 前调用');chain.doFilter(request, response); }}配置自定义 Filter 在 Spring Security 过滤器链中的位置
配置很简单,本文示例:
@Override protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers('/').permitAll().antMatchers('/user/**').hasAuthority('USER').and().formLogin().loginPage('/login').defaultSuccessUrl('/user').and().logout().logoutUrl('/logout').logoutSuccessUrl('/login');// 在 UsernamePasswordAuthenticationFilter 前添加 BeforeLoginFilterhttp.addFilterBefore(new BeforeLoginFilter(), UsernamePasswordAuthenticationFilter.class);// 在 CsrfFilter 后添加 AfterCsrfFilterhttp.addFilterAfter(new AfterCsrfFilter(), CsrfFilter.class); }
说明:
HttpSecurity 有三个常用方法来配置:
addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter)
在 beforeFilter 之前添加 filter
addFilterAfter(Filter filter, Class<? extends Filter> afterFilter)
在 afterFilter 之后添加 filter
addFilterAt(Filter filter, Class<? extends Filter> atFilter)
在 atFilter 相同位置添加 filter, 此 filter 不覆盖 filter
通过在不同 Filter 的 doFilter() 方法中加断点调试,可以判断哪个 filter 先执行,从而判断 filter 的执行顺序 。
spring security添加自定义过滤器1、定义自己的过滤器
2、指定位置,通过HttpSecurity的方法指定
定义过滤器package com.qiudaozhang.springsecurity.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class RequestHeadCheckFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {var httpRequest = (HttpServletRequest) servletRequest;var httpResponse = (HttpServletResponse) servletResponse;String requestId = httpRequest.getHeader('Request-id');if(requestId == null || requestId.isBlank()) { httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); return;}filterChain.doFilter(servletRequest,servletResponse); }}
package com.qiudaozhang.springsecurity.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class RequestParamCheckFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {var httpRequest = (HttpServletRequest) servletRequest;var httpResponse = (HttpServletResponse) servletResponse;String timestamp = httpRequest.getParameter('timestamp');if(timestamp == null || timestamp.isBlank()) { httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); return;}filterChain.doFilter(servletRequest,servletResponse); }}指定位置
HttpSecurity中有两个方法,指定过滤器的位置,一个指定在谁前面,一个指定在谁后面。
public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) { this.comparator.registerAfter(filter.getClass(), afterFilter); return this.addFilter(filter); } public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) { this.comparator.registerBefore(filter.getClass(), beforeFilter); return this.addFilter(filter); }
package com.qiudaozhang.springsecurity.config;import com.qiudaozhang.springsecurity.filter.RequestHeadCheckFilter;import com.qiudaozhang.springsecurity.filter.RequestParamCheckFilter;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;@Configurationpublic class ProjectConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(new RequestHeadCheckFilter(),BasicAuthenticationFilter.class).addFilterAfter(new RequestParamCheckFilter(),BasicAuthenticationFilter.class).authorizeRequests().anyRequest().permitAll(); }}测试
准备一个端点测试
package com.qiudaozhang.springsecurity.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController { @GetMapping('hello') public String hello () {return 'hello'; }}
当前没有传递timestamp参数,所以参照约定,过滤器直接给出403.
当前头部信息和参数信息都提供了,检测通过。
实际应用场景 检测相关的头部,参数等等信息日志过滤器,将所有请求的相关数据记录下来特殊的权限校验等等。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持好吧啦网。
相关文章: