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

作者:咸鱼最牛逼 时间:2023-11-24 02:48:35 

Spring Security 过滤器链及自定义Filter

别名类名称Namespace Element or Attribute
CHANNEL_FILTERChannelProcessingFilterhttp/intercept-url@requires-channel
SECURITY_CONTEXT_FILTERSecurityContextPersistenceFilterhttp
CONCURRENT_SESSION_FILTERConcurrentSessionFiltersession-management/concurrency-control
HEADERS_FILTERHeaderWriterFilterhttp/headers
CSRF_FILTERCsrfFilterhttp/csrf
LOGOUT_FILTERLogoutFilterhttp/logout
X509_FILTERX509AuthenticationFilterhttp/x509
PRE_AUTH_FILTERAbstractPreAuthenticatedProcessingFilter( Subclasses)N/A
CAS_FILTERCasAuthenticationFilterN/A
FORM_LOGIN_FILTERUsernamePasswordAuthenticationFilterhttp/form-login
BASIC_AUTH_FILTERBasicAuthenticationFilterhttp/http-basic
SERVLET_API_SUPPORT_FILTERSecurityContextHolderAwareRequestFilterhttp/@servlet-api-provision
JAAS_API_SUPPORT_FILTERJaasApiIntegrationFilterhttp/@jaas-api-provision
REMEMBER_ME_FILTERRememberMeAuthenticationFilterhttp/remember-me
ANONYMOUS_FILTERAnonymousAuthenticationFilterhttp/anonymous
SESSION_MANAGEMENT_FILTERSessionManagementFiltersession-management
EXCEPTION_TRANSLATION_FILTERExceptionTranslationFilterhttp
FILTER_SECURITY_INTERCEPTORFilterSecurityInterceptorhttp
SWITCH_USER_FILTERSwitchUserFilterN/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;
@Configuration
public 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;
@RestController
public class HelloController {
   @GetMapping("hello")
   public String hello () {
       return "hello";
   }
}

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

当前没有传递timestamp参数,所以参照约定,过滤器直接给出403.

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

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

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

来源:https://blog.csdn.net/panchang199266/article/details/90578947

标签:Spring,Security,过滤器链,Filter
0
投稿

猜你喜欢

  • Java Callable接口实现细节详解

    2023-11-10 05:34:26
  • 解决JavaWeb读取本地json文件以及乱码的问题

    2023-09-14 18:35:14
  • 浅谈Java线程Thread之interrupt中断解析

    2023-07-19 09:25:11
  • JavaEE开发之SpringMVC中的自定义消息转换器与文件上传

    2023-11-24 19:36:02
  • Java实现的不同图片居中剪裁生成同一尺寸缩略图功能示例

    2023-08-23 14:53:15
  • synchronized背后的monitor锁实现详解

    2023-07-31 08:14:10
  • Java集合TreeSet用法详解

    2023-11-10 22:53:34
  • java使double保留两位小数的多方法 java保留两位小数

    2023-06-17 14:01:30
  • Java C++实现相同MD5加密算法的方式

    2023-10-12 12:26:02
  • Redis 订阅发布_Jedis实现方法

    2023-11-10 03:38:41
  • 使用C#发送Http请求实现模拟登陆实例

    2023-06-22 22:25:07
  • Java字符判断的小例子

    2023-08-26 17:29:49
  • flutter窗口初始和绘制流程详析

    2023-08-17 21:07:30
  • java队列实现方法(顺序队列,链式队列,循环队列)

    2023-06-24 01:43:17
  • Android 使用 SharedPreferences 保存少量数据的实现代码

    2023-07-03 01:00:11
  • java获取和设置系统变量问题(环境变量)

    2023-11-19 07:34:07
  • synchronized及JUC显式locks 使用原理解析

    2023-08-05 03:28:41
  • Flutter基于Dart Unwrapping Multiple Optional小技巧

    2023-07-05 11:44:19
  • java 根据经纬度获取地址实现代码

    2023-09-05 04:54:50
  • kill命令在Java应用中使用的注意事项小结

    2023-11-11 13:01:55
  • asp之家 软件编程 m.aspxhome.com