Spring Security (一) 基础

Scroll Down

Spring Security 基础

1.初识SpringSecurity

对于SpringSecurity,可以由其官网中的介绍了解到其概述:

  1. SpringSecurity就是一个功能强大且高定制化的身份验证和访问控制框架,它事实上就是一个保护基于Spring的应用框架安全性的标准。
  2. Spring Security是一个重点为Java应用程序提供身份验证和授权的框架。
  3. 与所有Spring项目一样,Spring Security的真正强大之处在于它可以很容易地扩展以满足定制需求

对于SpringSecurity的特性,可以总结为以下几点:

  1. 对身份认证和授权提供全面和可扩展的支持。
  2. 防止会话固定、劫持请求、跨站点请求伪造等攻击。
  3. Servlet API的集成。
  4. 与Spring Web MVC的可选集成。

2.Spring Security项目核心jar包介绍

在SpringSecurity继承的项目中,主要有四个核心的jar包:

  • spring-security-core.jar
    SpringSecurity的核心包,任何SpringSecurity的功能都需要此包。
  • spring-security-web.jar
    web工程必备,包含过滤器和相关的Web安全基础结构代码。
  • spring-security-config.jar
    用于解析xml配置文件,用到SpringSecurity的xml配置文件的就要用到此包。
	<!-- 导入SpringSecurity相关依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

image-20210724104039174

3.SpringSecurity核心注解

3.1@EnableWebSecurity

@EnableWebSecurity是Spring Security用于启用Web安全的注解。

该注解用在某个Web安全配置类上(实现了接口WebSecurityConfigurer或者继承自WebSecurityConfigurerAdapter)。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
}

image-20210724104445191

从注解源码可以看到,该注解有如下作用:

  1. 控制Spring Security是否使用调试模式(通过注解属性debug指定),默认为false,表示缺省不使用调试模式。
  2. 导入 WebSecurityConfiguration,用于配置Web安全过滤器FilterChainProxy,并创建过滤器链springSecurityFilterChain来保护你的Spring应用。
  3. 如果是Servlet 环境,导入WebMvcSecurityConfiguration。
  4. 如果是OAuth2环境(spring-security-oauth2-client),导入OAuth2ClientConfiguration。
  5. 使用注解@EnableGlobalAuthentication启用全局认证机制,即全局的AuthenticationManager,AuthenticationManager会在运行时对请求着进行身份验证。

3.2 @EnableGlobalAuthentication

@EnableGlobalAuthentication是包含在了@EnableWebSecurity注解中的,作用通过启用认证管理器(AuthenticationManager)来启用全局认证机制。

image-20210724111609197

核心逻辑就在AuthenticationConfiguration类里。

在AuthenticationConfiguration在SpringSecurity中扮演者非常重要的作用,它内部包含了AuthenticationManager用于核心的认证工作。

3.3 @EnableGlobalMethodSecurity

Spring Security默认是禁用注解的,要想开启注解,需要在继承WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解,来判断用户对某个控制层的方法是否具有访问权限。

除此之外,还可以在@EnableGlobalMethodSecurity中添加几个属性。

  1. @EnableGlobalMethodSecurity(securedEnabled=true)开启@Secured 注解过滤权限。
  2. @EnableGlobalMethodSecurity(jsr250Enabled=true)开启@RolesAllowed 注解过滤权限 。
  3. @EnableGlobalMethodSecurity(prePostEnabled=true)使用表达式时间方法级别的安全性 4个注解可用。
    • @PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问
    • @PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常
    • @PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果
    • @PreFilter 允许方法调用,但必须在进入方法之前过滤输入值

4.SpringSecurity核心组件

在SpringSecurity中,有着许多的组件包括AuthenticationManager、AccessDesicionManager和UsernamePasswordAuthenticationFilter等。

对于SpringSecurity来说,最大的两个问题就是:认证(Authentication,即你是谁?)和授权(Authorization,允许你做什么?)。SpringSecurity框架旨在将认证从授权中剥离出来,并也有适用于二者的策略和可扩展的设计。

4.1 认证

在SpringSecurity中,用于认证的主要接口是AuthenticationManager,它只有一个方法:

image-20210724154017306

AuthenticationManger最普遍的实现类是ProviderManager,而ProviderManager会将认证委托给AuthenticationProvider。

image-20210724155153991

AuthenticationProvider接口和AuthenticationManager相似,但是它有一个额外的方法允许查询它支持的Authentication方式:

public interface AuthenticationProvider {
	Authentication authenticate(Authentication authentication)
			throws AuthenticationException;

	boolean supports(Class<?> authentication);
}

4.2 授权

一旦认证成功,我们就可以进行授权了,它核心的策略就是AccessDecisionManager。同样的,它将授权逻辑全部委托给AccessDecisionVoter来实现。

一个AccessDecisionVoter考虑一个Authentication(代表一个Principal)和一个被ConfigAttributes装饰的安全对象,这里的ConfigAttributes就是一个包含了URL以及这个URL该有权限的对象的集合。

boolean supports(ConfigAttribute attribute);

boolean supports(Class<?> clazz);

int vote(Authentication authentication, S object,
        Collection<ConfigAttribute> attributes);

现在,已经拥有了认证和授权组件了,那么一个HTTP请求进入SpringSecurity应用时,经过过滤器链中都发生了哪些逻辑?接下来就看下SpringSecurity中过滤器链底层都发生了什么。

5.SpringSecurity中的Filter

除了认证和授权外,SpringSecurity的另外一个核心就是Servlet的Filter来实现的。先简单回顾下Servlet中Filter的调用原理。
下图展示了处理单个HTTP请求的经典分层结构图:

拦截器

客户端向服务器发起请求,然后Servlet容器(Tomcat)会根据URI来决定哪个Filter和哪个Servlet适用于这个请求,一个Servlet最多处理一个请求,过滤器是链式的,它们是有顺序的。事实上一个过滤器可以否决接下来的过滤器,上一个过滤器请求处理完就会通过调用Filter的doFilter()向下传递请求,直到请求最终到达Servlet处理完毕后,再过滤器以相反的顺序调用,再以Response返回给客户端。

5.1 FilterChainProxy以及其内部的Filter

回归正题,SpringSecurity在过滤器链中扮演的就是一个Filter,其类型是FilterChainProxy。但它又不是一个普通的Filter,因为FilterChainProxy中包含了额外的过滤器,每个过滤器都发挥特殊的作用。下面用一张图展示下FliterChainProxy中包含的过滤器链。

springsecurityfilter

在SpringBoot中,SpringSecurity的FilterChainProxy是以bean的形式注入到Spring容器中的,并且它是默认配置,所以在每次请求中都会存在,所以在SpringSecurity保护的应用中,每次请求都会经过FilterChainProxy。

总结

本片文章粗略的讲解了SpringSecurity里的几个核心概念,包括:核心注解、认证和授权的核心组件以及SpringSecurity中的FilterChainProxy,整个SpringSecurity框架就是围绕着这几个核心概念运行,下面几章将会深入分析每个核心概念的底层运行机制。

参考

以及感谢CoderBruis 主流框架分析 :https://github.com/coderbruis/JavaSourceCodeLearning