过滤器可以简单理解成用于拦截请求,并执行相应逻辑的代码。

在Spring Security架构中实现过滤器

在SpringSecurity中,可以通过实现 javax.servlet 包中的 Filter接口构造过滤器。

我们通过实现Filter 接口的doFilter() 方法,执行相关逻辑。该方法包含三个参数:

  1. ServletRequest:表示http请求,可用它获得请求相关信息。
  2. ServletResponse:表示http响应,可向它添加相关信息,最后传回客户端。
  3. FilterChain:表示过滤链,用于把请求和响应转发到过滤链上的下一个过滤器。

Spring Security为我们提供了一些过滤器实现,例如:

  • BasicAuthenticationFilter:用于http认证。
  • CsrfFilter:用于跨请求保护。
  • CorsFilter:负责跨域资源共享 (CORS) 授权规则。

多个过滤器集合在一起形成一条过滤链,它们之间有一定顺序。你可以通过存在于过滤链上的一个过滤器,在它的相对位置添加一个新的过滤器。

在过滤链上的一个过滤器前面,添加一个新的过滤器

可以通过下面的方法在某过滤器前面添加一个新的过滤器。

@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new CustomFilter(), BasicAuthenticationFilter.class);
} }

CustomFilter是你自定义实现的过滤器类,BasicAuthenticationFilter是认证过滤器的默认类型。

在过滤链上的一个过滤器后面,添加一个新的过滤器

下面的代码是在某过滤器后面添加一个新的过滤器。

@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class);
} }

在过滤链上的一个过滤器位置,添加一个新的过滤器

下面代码是在一个过滤器的位置上,添加一个新的过滤器。

@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http..addFilterAt(new CustomFilter(), BasicAuthenticationFilter.class);
} }

当在一个过滤器的位置上,加入一个新的过滤器,Spring Security不会假设该位置上只有一个过滤器, 它也不会保证该位置上过滤器的顺序。

Spring Security 提供的过滤器实现

Spring Security 提供了一些实现Filter借口的抽象类,并在里面加入一些功能。你可以通过继承这些类来构建过滤器类。例如OncePerRequestFilter等。由于Spring Security不能保证一个过滤器对于同一个请求不会被调用多次,我们可以是过滤器继承OncePerRequestFilter来保证。

演示代码

在过滤器BasicAuthenticationFilter的前面、当前位置、后面各添加一个新的过滤器。

创建一个SpringBoot项目,它的依赖如下:

    <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

创建三个过滤器,分别为BeforeFilter、CurrentFilter、AfterFilter。

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class BeforeFilter implements Filter { @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("BeforeFilter: " + "在其前面插入的过滤器");
chain.doFilter(request, response);
} }
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class CurrentFilter implements Filter { @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("CurrentFilter: " + "在其当前位置插入的过滤器");
chain.doFilter(request, response);
} }
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class AfterFilter implements Filter { @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("AfterFilter: " + "在其后面插入的过滤器");
chain.doFilter(request, response);
} }

创建一个配置类ProjectConfig

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; import hookind.security009.filter.AfterFilter;
import hookind.security009.filter.BeforeFilter;
import hookind.security009.filter.CurrentFilter; @Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll();
// 在前面加入一个过滤器
http.addFilterBefore(new BeforeFilter(), BasicAuthenticationFilter.class);
// 在当前位置加入一个过滤器
http.addFilterAt(new CurrentFilter(), BasicAuthenticationFilter.class);
// 在其后面加入一个过滤器
http.addFilterAfter(new AfterFilter(), BasicAuthenticationFilter.class);
}
}

创建一个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";
}
}

启动程序后,在浏览器输入网址 http://localhost:8080/hello,我的控制台输出如下:

BeforeFilter: 在其前面插入的过滤器
CurrentFilter: 在其当前位置插入的过滤器
AfterFilter: 在其后面插入的过滤器
BeforeFilter: 在其前面插入的过滤器
CurrentFilter: 在其当前位置插入的过滤器
AfterFilter: 在其后面插入的过滤器
BeforeFilter: 在其前面插入的过滤器
CurrentFilter: 在其当前位置插入的过滤器
AfterFilter: 在其后面插入的过滤器

由上可知,过滤器是按BeforeFilter、CurrentFilter、AfterFilter顺序调用的。也表示,对于同一个请求,Spring Security可能会调用同一个过滤器多次。

Spring Security Filter 学习笔记的更多相关文章

  1. spring security原理-学习笔记1-整体概览

    整体概述 运行时环境 Spring Security 3.0需要Java 5.0 Runtime Environment或更高版本. 核心组件 SecurityContextHolder,Securi ...

  2. spring security原理-学习笔记2-核心组件

    核心组件 AuthenticationManager,ProviderManager和AuthenticationProvider AuthenticationManager只是一个接口,实际中是如何 ...

  3. Find security bugs学习笔记V1.0

    Find security bugs学习笔记V1.0 http://www.docin.com/p-779309481.html

  4. Spring Security Filter详解

    Spring Security Filter详解 汇总 Filter 作用 DelegatingFilterProxy Spring Security基于这个Filter建立拦截机制 Abstract ...

  5. spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)

    绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...

  6. Spring源码学习笔记9——构造器注入及其循环依赖

    Spring源码学习笔记9--构造器注入及其循环依赖 一丶前言 前面我们分析了spring基于字段的和基于set方法注入的原理,但是没有分析第二常用的注入方式(构造器注入)(第一常用字段注入),并且在 ...

  7. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  8. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  9. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

随机推荐

  1. 洛谷 P3700 - [CQOI2017]小Q的表格(找性质+数论)

    洛谷题面传送门 又是一道需要一些观察的数论 hot tea-- 注意到题目中 \(b·f(a,a+b)=(a+b)·f(a,b)\) 这个柿子长得有点像求解 \(\gcd\) 的辗转相除法,因此考虑从 ...

  2. [Linux] 非root安装GCC9.1.0

    说明 一般Linux系统自带或公共的GCC版本都很低,如目前我们的服务器版本的GCC还停留在gcc-4.9.3,而官网已到达9.2版本(下载http://ftp.gnu.org/gnu/gcc/) , ...

  3. 基本绘图函数:plot的使用

    注意:"##"后面是程序输出结果 例如: par("bg") # 命令 ## [1] "white" # 结果 基本绘图函数: plot:散 ...

  4. idea 启动debug的时候throw new ClassNotFoundException(name)

    idea 启动debug的时候throw new ClassNotFoundException(name) 启动debug就跳转到此界面 解决办法 这个方法只是忽略了抛异常的点,并没有真正解决问题.后 ...

  5. 学习java 7.8

    学习内容: 被static修饰的不需要创建对象,直接用类名引用即可 内部类访问特点:内部类可以直接访问外部类的成员,包括私有 外部类访问内部类的成员,必须创建对象 成员内部类,内部类为私有,Outer ...

  6. 学习Vue源码前的几项必要储备(一)

    从接下来的一段时间里,Mg要进行阅读源码的工作.再阅读源码前,梳理一下准备工作. 7项重要储备 Flow 基本语法 发布/订阅模式 ES6+ 语法 原型链.闭包 函数柯里化 event loop 1. ...

  7. 内存中 1k 代表什么

    1K也就是 1KB   == 1000 bytes == 1000 *8 位 通常一个地址里面有8位,就是说一个房间里面能存8个0或者1

  8. C++构造函数和析构函数初步认识(2)

    构造函数的三个作用1.构造对象2.对象初始化3.类型转换  //Test1.h #include<iostream> using namespace std; //构造对象 //初始化对象 ...

  9. HelloWorldModelMBean

    package mbeanTest; import java.lang.reflect.Constructor; import javax.management.Descriptor; import ...

  10. Android Loader异步装载

    一.Loader简介: (一).Loader的概念: 装载器从android3.0开始引进.它使得在activity或fragment中异步加载数据变得简单. 当成批显示数据的时候,为了使用户体验更好 ...