Spring Security之默认的过滤器链及自定义Filter操作

Spring Security 过滤器链及自定义Filter

别名 类名称 Namespace Element or Attribute CHANNEL_FILTER ChannelProcessingFilter http/intercept-url@requires-channel SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter http CONCURRENT_SESSION_FILTER ConcurrentSessionFilter session-management/concurrency-control HEADERS_FILTER HeaderWriterFilter http/headers CSRF_FILTER CsrfFilter http/csrf LOGOUT_FILTER LogoutFilter http/logout X509_FILTER X509AuthenticationFilter http/x509 PRE_AUTH_FILTER AbstractPreAuthenticatedProcessingFilter( Subclasses) N/A CAS_FILTER CasAuthenticationFilter N/A FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter http/form-login BASIC_AUTH_FILTER BasicAuthenticationFilter http/http-basic SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http/@servlet-api-provision JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http/@jaas-api-provision REMEMBER_ME_FILTER RememberMeAuthenticationFilter http/remember-me ANONYMOUS_FILTER AnonymousAuthenticationFilter http/anonymous SESSION_MANAGEMENT_FILTER SessionManagementFilter session-management EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http SWITCH_USER_FILTER SwitchUserFilter N/A

过滤器顺序从上到下

自定义 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 前添加 BeforeLoginFilter        http.addFilterBefore(new BeforeLoginFilter(), UsernamePasswordAuthenticationFilter.class);        // 在 CsrfFilter 后添加 AfterCsrfFilter        http.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.

当前头部信息和参数信息都提供了,检测通过。

实际应用场景 检测相关的头部,参数等等信息日志过滤器,将所有请求的相关数据记录下来特殊的权限校验等等。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

宁愿停歇在你门前的那棵树上,看着你,守护你。

Spring Security之默认的过滤器链及自定义Filter操作

相关文章:

你感兴趣的文章:

标签云: