欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-06 22:21:23
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";
    }
}

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

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

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

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

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

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