Spring Security之默认的过滤器链及自定义Filter操作
程序员文章站
2022-07-05 19:23:46
spring security 过滤器链及自定义filter 别名 类名称 namespace element...
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; @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"; } }
当前没有传递timestamp参数,所以参照约定,过滤器直接给出403.
当前头部信息和参数信息都提供了,检测通过。
实际应用场景 检测相关的头部,参数等等信息日志过滤器,将所有请求的相关数据记录下来特殊的权限校验等等。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
上一篇: 现在的女生都怎么了
下一篇: SpringBoot实现线程池