Spring Security(一)架构概览

一、 Spring Security 架构概览

1. Spring Security 简介

在Java企业级开发中,安全管理方面的框架非常少,一般来说,主要是三种方案:

  • Shiro
  • Spring Security
  • 开发者自己实现

Spring Security基于Spring框架,提供了一套Web应用安全性的完整解决方案。一般来说,Web应用的安全性包括用户认证 (Authentication)和用户授权(Authorization)两个部分。

2. Spring Security 核心功能

1)用户认证 (Authentication)

用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。

Spring Security集成的主流认证机制包括:

  • 表单认证
  • OAuth2.0
  • CAS认证
  • RememberMe自动认证
  • ...
2)**用户授权 (Authorization) **

用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

3)其他

Spring Security 还提供了很多按钮全管理的"周边功能",例如,CSRF攻击、会话固定攻击等,同时Spring Security 还提供了 HTTP 防火墙来拦截大量的非法请求。

3. Spring Security 整体框架

1)认证

在 Spring Security 中,用户的认证信息主要由 Authentication 的实现类来保存,Authentication 接口定义如下:

java 复制代码
public interface Authentication extends Principal, Serializable {
    // 用来获取用户的权限
    Collection<? extends GrantedAuthority> getAuthorities();
    // 用来获取用户凭证,一般来说就是密码
    Object getCredentials();
	// 用来获取用户携带的详细信息,可能是当前请求之类等
    Object getDetails();
	// 有用来获取当前用户,例如一个用户名或者一个用户对象
    Object getPrincipal();
	// 当前用户是否认证成功
    boolean isAuthenticated();

    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

当用户使用用户名/密码登录或者使用 Remember-me 登录时,都会对应一个不同的 Authentication 实例。

Spring Security 中的认证工作主要是由 AuthenticationManager接口来负责:

java 复制代码
public interface AuthenticationManager {
    /** AuthenticationManager 只有一个 authenticate 方法可以用来做认证,该方法有三个不同的返回值:
    *   1. 返回 Authentication,表示认证成功
    *   2. 抛出 AuthenticationException 异常,表示用户输入了无效的凭证。
    *   3. 返回null,表示不能断定。
    */  
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

在介绍了 AuthenticationManager 之后,我们介绍 AuthenticationManager 的主要实现类 ProviderManager,ProviderManager 管理了众多的 AuthenticationProvider 实例。

java 复制代码
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
    private List<AuthenticationProvider> providers;
    
    public ProviderManager(AuthenticationProvider... providers) {
        this(Arrays.asList(providers), (AuthenticationManager)null);
    }
    
    public ProviderManager(List<AuthenticationProvider> providers, AuthenticationManager parent) {
        this.eventPublisher = new NullEventPublisher();
        this.providers = Collections.emptyList();
        this.messages = SpringSecurityMessageSource.getAccessor();
        this.eraseCredentialsAfterAuthentication = true;
        Assert.notNull(providers, "providers list cannot be null");
        this.providers = providers;
        this.parent = parent;
        this.checkState();
    }
}
java 复制代码
public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
	// supports 方法用来判断是否支持给定的 Authentication 类型
    boolean supports(Class<?> authentication);
}

由于 Authentication 拥有众多的实现类,这些不同的实现类又有不同的 AuthenticationProvider 来处理,所以 AuthenticationProvider 会有一个 supports 方法来判断当前的 AuthenticationProvider 是否支持对应的 Authentication。

再一次完整的认证过程中,可能会存在多个 AuthenticationProvider (比如一个项目同时存在form表单登录和短信验证码登录),多个AuthenticationProvider 统一由 ProviderManager 来管理。如果所有的 AuthenticationProvider 都认证失败了,那么就会电泳 parent 进行认证,相当于是一个备用认证方式。

2)授权

在 Sping Security 的授权体系中,有两个关键接口:

  • AccessDecisionManager

    它是一个决策器,来决定此次访问是否被允许。

  • AccessDecisionVoter

    它是一个投票器,投票器会检查用户是否具备应有的角色,进而投出赞成、反对或弃权。

它们都有众多的实现类,在 AccessDecisionManager 会挨个访问 AccessDecisionVoter,进而决定是否允许用户访问,因此,AccessDecisionVoter 和 AccessDecisionManager 的关系似于 AuthenticationProvider 和 ProviderManager 之间的关系。

3)Web安全

在 Spring Security 中,认证和授权都是基于过滤器来完成的。这些过滤器按照既定的优先级排列,最终形成一个过滤器链。开发者也可以通过自定义过滤器,并通过@Order注解来调整自定义过滤器在过滤器链中的位置,并通过FiliterChainProxy来统一管理。Spring Security 中的过滤器链通过FiliterChainProxy 嵌入到 Web 项目的原生过滤器链中。

4) 登录数据保护

当用户登录成功后,Spring Security会将登录成功的用户信息保存到 SecurityContextHolder 中。存入其中的数据默认通过ThreadLocal 来实现的。用户数据是和当前请求线程绑定在一起的。当登录请求处理完毕后, Spring Security 会将 SecurityContextHolder 中的数据拿出来保存到Session 中, 同时,将 SecurityContextHolder 中的数据清空。

《深入浅出 Spring Security》 王松 著

相关推荐
草莓base15 分钟前
【手写一个spring】spring源码的简单实现--bean对象的创建
java·spring·rpc
乌啼霜满天24943 分钟前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
Elaine2023911 小时前
零碎04 MybatisPlus自定义模版生成代码
java·spring·mybatis
.生产的驴4 小时前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
码蜂窝编程官方6 小时前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
AuroraI'ncoding7 小时前
时间请求参数、响应
java·后端·spring
计算机毕设指导69 小时前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
ExiFengs10 小时前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
瓜牛_gn11 小时前
依赖注入注解
java·后端·spring
一元咖啡12 小时前
SpringCloud Gateway转发请求到同一个服务的不同端口
spring·spring cloud·gateway