Spring Security 架构

本文深入解析SpringSecurity框架,涵盖其核心功能、架构设计与实现原理,包括认证、授权、权限管理及自定义决策机制,适合对SpringSecurity感兴趣的技术人员阅读。

最近开始准备做一个项目,找了慕课的权限管理系统,开始学习spring seurity框架,这里记录一下这个框架的架构

是什么

一个能够为基于Spring的企业应用系统提供声明式的安全訪问控制解决方式的安全框架(简单说是对访问权限进行控制嘛),应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 spring security的主要核心功能为 认证和授权,所有的架构也是基于这两个核心功能去实现的。

简单来说:Spring Security 主要实现了Authentication(认证,解决who are you? ) 和 Access Control(访问控制,也就是what are you allowed to do?,也称为Authorization)。Spring Security在架构上将认证与授权分离,并提供了扩展点。

核心对象

首先我们看一下Spring Security中的三个核心对象SecurityContextHolder, SecurityContext 和 Authentication

SecurityContextHolder是SecurityContext的存放容器,使用ThreadLocal存储,意味着SecurityContext在相同的线程中的方法都是可用的。
SecurityContext主要的存储应用的principal信息,然后在Spring Security中用 Authentication来表示。

这里贴上获取principal的方式

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}

然后我们看一下对于Authentication的定义

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();            //通常是密码

    Object getCredentials();       //更多细节信息来标识用户,可能是ip地址

    Object getDetails();        //标识是否已经认证,如果是用户密码登陆则这里通常是用户名

    Object getPrincipal();      //是否认证

    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

一个常见的认证过程通常是这样的,创建一个UsernamePasswordAuthenticationToken,然后交给authenticationManager认证,认证通过SecurityContextHolder存放Authentication的信息

UserDetails与UserDetailService

UserDetails是Spring Security里的一个关键接口,他表示一个principal

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

UserDetails 提供了认证所需的必要信息,在实际使用里,可以自己实现UserDetails,并增加额外的信息,比如email、mobile等信息。

在Authentication中的principal的通常是用户名,我们可以通过UserDetailService获取UserDetails;

小结

  • SecurityContextHolder, 用来访问 SecurityContext.

  • SecurityContext, 用来存储Authentication .

  • Authentication, 代表凭证.

  • GrantedAuthority, 代表权限.

  • UserDetails, 用户信息.

  • UserDetailsService,获取用户信息.

web security的实现方式

Web层中的Spring Security(用于UI和HTTP后端)基于Servlet Filters,下图显示了单个HTTP请求的处理程序的典型分层。
在这里插入图片描述
Spring Security通过FilterChainProxy作为单一的Filter注册到web层,Proxy内部的Filter。
在这里插入图片描述
FilterChainProxy相当于一个filter的容器,通过VirtualFilterChain来依次调用各个内部filter

不同的filter拦截器

1.SecurityContextPersistenceFilter

  • 位于过滤器的顶端,是起作用的第一层过滤器,在别的过滤器之前率先判断session是否存在上下文
SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder);
  • 在所有过滤器之后清空spring security内容
 SecurityContextHolder.clearContext();

2.LogoutFilter 用户发送注销请求时候清空session和applicationContext,同时可以配合其他的去清空cookie

3.AbstractAuthenticationProcessingFilter 处理form登陆的过滤器

与form有关的所有登陆在此执行,判断用户名和密码然后跳转对应成功和错误

4.DefaultLoginPageGeneratingFiler 默认登陆页面(丑)

5.BaseicAuthenticationFilter 与AbstractAuthenticationProcessingFilter 类似,只是验证的方式不同

6.SecurityContextHolderAwareRequestFilter 用来包装客户的信息,用来返回对应get/set

7.RememberMeAuthenticationFilter 通过cookie免登陆

8.AnoymousAuthenticationFilter 匿名登陆

9.ExceptionTranslation 异常控制

10.SessionManagementFilter 防止攻击

11.FilterSecurityInterceptor

核心处理流程

在这里插入图片描述

数据库管理
  • 当一个用户登陆时候,先执行身份认证,如果认证未通过,重新认证。
  • 当用户认证通过,调用角色管理器判断他能否访问,这里就是用到spring security提供的UserDetails,Authentication是spring security使用的安全访问控制用户信息的安全对象,这里的UserDetails是用户的信息原
  • 当我们需要使用数据库管理用户时候,我们需要手动实现UserDetailsService接口中的loadUserByUsername方法,这就需要我们在数据库中准备3张表:用户表、权限表、角色表、用户和角色关系表、权限和角色关系表。
  • 这样我们就把用户登陆放到数据库中管理了
权限缓存

CachingUserDetailService类

  • 这个类的构造方法接收了用于真正加载UserDetails的UserDetailsService实现类
  • 当需要UserDeatils时候,会优先从缓存中获取,如果缓存中没有Details存在,就会用UserDetailsService的实现类来加载,然后存在缓存中
  • Details跟缓存的交互就是通过UserCache来实现

实际项目中,会使用别的缓存,redis之类来缓存别的信息。

自定义决策

当用户通过认证,调用决策管理器AbstractAccessDecisionManager,其中有判断方法supports,其中的参数decisionVoters类型是AccessDesionvoter,他是spring security引入的投票器的概念,最终决定权就是投票器决定

RoleVoter中vote方法会循环判断是否通过,最终返回ACCESS_GRANTED

目前三种投票器:

  • AffirmativeBased(一票通过)
  • ConsensusBased(半数通过)
  • UnanimousBased(全数通过)
### Spring Security 架构详解及核心组件 Spring Security 是一个强大的安全框架,专注于身份验证和授权功能。它提供了全面的安全解决方案,适用于各种应用场景,尤其是在微服务架构中具有重要作用。 #### 1. **Spring Security 的整体架构** Spring Security架构基于过滤器链模型(Filter Chain),所有的请求都会经过一系列的过滤器处理。这种设计使得安全性可以灵活地嵌入到应用程序的不同阶段。以下是其主要组成部分: - **Security Filter Chain**: 这是一个由多个 `Filter` 组成的链条,用于拦截 HTTP 请求并执行相应的安全逻辑[^2]。 - **Authentication Mechanism (认证机制)**: 负责用户的登录过程,支持多种认证方式,如表单登录、HTTP 基本认证以及 OAuth2 认证等[^3]。 - **Authorization Mechanism (授权机制)**: 控制用户访问资源的权限,通常通过角色或权限表达式实现[^4]。 --- #### 2. **Spring Security 的核心组件** ##### (1)**AuthenticationManager 和 ProviderManager** `AuthenticationManager` 接口负责管理整个认证流程,而其实现类 `ProviderManager` 则会调用一组预定义的 `AuthenticationProvider` 来完成具体的认证工作。如果某个 `AuthenticationProvider` 成功完成了认证,则返回已认证的对象;否则继续尝试下一个提供者。 ##### (2)**UserDetailsService** 这是 Spring Security 中最常用的接口之一,用于加载用户特定的数据。开发者可以通过自定义该接口来获取用户信息,并将其转换为 `UserDetails` 对象供后续使用。 ```java @Service public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 自定义逻辑查询数据库或其他数据源 return new org.springframework.security.core.userdetails.User( "user", "{noop}password", AuthorityUtils.createAuthorityList("ROLE_USER")); } } ``` ##### (3)**AccessDecisionManager** 此组件决定是否允许主体访问受保护对象。常见的决策策略包括一致同意 (`UnanimousBased`)、多数投票 (`AffirmativeBased`) 或一票否决权 (`ConsensusBased`) 等。 ##### (4)**Remember-Me 功能** 当启用 Remember-Me 配置时,即使浏览器关闭后,用户仍然能够保持登录状态。这通常是通过 Cookie 实现的。 ```yaml spring: security: user: name: user password: password remember-me: token-validity-seconds: 86400 # 设置记住我的有效期为一天 ``` ##### (5)**LogoutHandler 和 LogoutSuccessHandler** 这两个处理器分别用来清理与注销相关的操作(例如清除 Session 和 Cookies),以及指定注销成功后的重定向地址。 ```java @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public LogoutSuccessHandler logoutSuccessHandler() { return new SimpleUrlLogoutSuccessHandler(); } @Override protected void configure(HttpSecurity http) throws Exception { http.logout() .logoutSuccessUrl("/login?logout") // 注销成功跳转至登录页 .invalidateHttpSession(true); // 清理 HttpSession } } ``` ##### (6)**OAuth2 支持** 随着现代应用对第三方登录的需求增加Spring Security 提供了内置的支持以集成 OAuth2 协议。它可以作为客户端或者资源服务器运行,在微服务环境中尤其有用。 --- #### 总结 Spring Security 不仅提供了丰富的开箱即用的功能,还允许开发人员高度定制化自己的需求。无论是简单的用户名密码校验还是复杂的分布式环境下的多层防护体系,都可以借助这一工具轻松实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值