文章目录
- 1、信息安全基础
- 2、Spring Security
- 1. Spring Security 简介
- 2. Spring Security 架构核心
- 2.1 FilterChain (Servlet)
- 2.2 [DelegatingFilterProxy](https://docs.spring.io/spring-security/reference/6.0.0-M3/servlet/architecture.html#servlet-delegatingfilterproxy)(Spring)
- 2.3 [FilterChainProxy](https://docs.spring.io/spring-security/reference/6.0.0-M3/servlet/architecture.html#servlet-filterchainproxy) (Spring Security)
- 2.4 [SecurityFilterChain](https://docs.spring.io/spring-security/reference/6.0.0-M3/servlet/architecture.html#servlet-securityfilterchain)
- 3. Spring Security 认证
- 4. Spring Security 授权
- 5. Spring Security 实践
- 3、Spring Oauth2 - 分布式版本的Security框架
参考文献
- Spring Security 相关:
- Oauth2 相关:
- 信息安全理论相关:
- 测试相关:
1、信息安全基础
1. CIA 三要素
在介绍访问控制的概念之前,有必要先介绍信息安全的一个基本原理,帮助我们更好地理解访问控制解决了信息安全的什么问题。
信息安全的内容可以简化为下列三个基本点,称为 CIA 三要素:
- Confidentiality(保密性):指保持信息 安全与私密 的需要。
例如,我们的银行卡密码在银行系统中只有我们自己能知道,如果除此以外的人知道了,那么则说明这个系统是不满足信息安全 Confidentiality 条件的,那么这个系统就是不安全的。
- Integrity(完整性):是指保护信息不被未经授权的用户 不当更改或修改 的概念。
例如,我们的银行卡密码不能被其他任何人更改,只有我们自已或者经过我们确认授权的安全管理员才能更改密码。
- Availability(可用性):指信息可在需要时使用的概念。
例如针对 Web 服务过载的攻击(DDoS)就是对可用性的攻击。
**访问控制 **对于保证信息的 Confidentiality 和 Integrity 至关重要。Confidentiality 条件要求只有授权用户才能读取信息,而 Integrity 条件要求只有授权用户才能以授权方式更改信息。
**访问控制 **在保持可用性方面作用不太明显,但它显然具有重要作用:例如对于一个接口,平均响应时间3s,在没有访问控制时,任意一个人都能发起大量请求让系统down掉;但如果有访问控制,那么恶意攻击者的未授权请求就直接被快速拒绝掉,避免对系统负载造成影响。
2. Authentication Vs. Authorization
用户认证(Authentication)和 授权(Authorization)是访问控制(Access Control)的基础。它们是不同的概念,但经常混淆。部分混淆源于两者之间的密切关系:正确的授权实际上取决于认证。
- 认证
**认证 **是确定用户声明的身份是否合法的过程。
- 授权
虽然身份认证是一个确定我是谁的过程,但授权决定了我们可以做什么。授权是指关于“是否授予用户访问系统资源的权限”的决定。信息系统必须维护用户ID和系统资源之间的某种关系,可能通过将授权用户列表附加到资源,或通过存储每个用户 ID 的可访问资源列表。
3. RBAC模型
目前主流的访问控制模型:RBAC模型——基于角色的访问控制。而 Spring Security 框架就是 RBAC 模型的一种实现。
四个基本要素:用户(U)、角色®、会话(S)和权限§
RBAC模型 是目前国际上流行的先进的安全访问控制方法。它通过分配和取消角色来完成用户权限的授予和取消,并且提供角色分配规则;
整个访问控制**过程分两个部分:**访问权限与角色相关联,角色再与用户关联,从而实现了用户与访问权限的逻辑分离。
**优点:**简化了用户和权限的关系,易扩展、易维护。
**缺点:**RBAC模型没有提供操作顺序的控制机制,这一缺陷使得 RBAC模型 难以适应那些对操作次序有严格要求的系统。
2、Spring Security
1. Spring Security 简介
- https://wukong-doc.redhtc.com/security/spring/spring-security-review/
- Spring Security 是一个功能强大且高度可定制的身份认证和访问控制框架。它实际上是保护基于 Spring 的应用程序的标准。
- Spring Security是一个框架,侧重于为 Java应用程序 提供身份认证和授权。与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松地扩展以满足定制需求。
2. Spring Security 架构核心
2.1 FilterChain (Servlet)
责任链设计模式:责任链模式是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
FilterChain 中的 Filters 主要有两方面作用:
- 修改 HttpServletRequest 或 HttpServletResponse,这样 FilterChain 后续的 Filters 或 Servlet 得到的就是被修改后的请求和响应内容。
- Filter 会拦截请求,自己作出响应,相当于断开了 FilterChain,导致后续的 Filters 和 Servlet 无法接收到该请求。
2.2 DelegatingFilterProxy(Spring)
- Spring 提供了一个 DelegatingFilterProxy 代理类,它实现了 Filter,因此可以被注入到 FilterChain 中;同时,当请求到来时,它会把请求转发到 Spring 容器中实现了 Filter 接口的 Bean 实体,所以 DelegatingFilterProxy 桥接了 Servlet 容器和 Spring 容器。
2.3 FilterChainProxy (Spring Security)
- 其作用是用来管理 Spring Security 中各种过滤器链(并非 Servlet 容器中的过滤器链),可以认为是 Spring Security 功能的入口。FilterChainProxy 被包裹在 DelegatingFilterProxy 中,因此调用时机也由 DelegatingFilterProxy 决定。
2.4 SecurityFilterChain
- Security Filters 通过 SecurityFilterChain API 被关联到FilterChainProxy,往往多个SecurityFilterChain负责不同的任务。
- Security默认过滤器实例的顺序很重要。
3. Spring Security 认证
3.1 认证流程
这里介绍 Spring Security 的登录认证功能是如何实现的。
具体流程如下:
- SecurityContextHolder - 是 Spring Security 存储身份验证人员详细信息的地方。
- SecurityContext - 通过SecurityContextHolder获取,包含了经过身份验证的用户的Authentication。
- Authentication - 可以通过AuthenticationManager进行身份验证后产生,或者直接从SecurityContext得到。
- AuthenticationManager - 定义 Spring Security 的过滤器如何执行身份验证的 API 。这是一个接口,只有一个函数 authenticate。
- ProviderManager - 最常见的 AuthenticationManager 实现,这个类可以管理多个 Provider。
- AuthenticationProvider - 用于 ProviderManager 执行特定类型的身份验证。这是一个接口,里面有一个authenticate与supports函数,Spring 中大部分认证的内置类都继承了这个接口。
- UserDetailsService - 是 DaoAuthenticationProvier 与特定用户信息来源进行解耦的地方,UserDetailsService 由 UserDetails 和 UserDetailsManager 所构成;UserDetails 和 UserDetailsManager各司其责,一个是对基本用户信息进行封装,一个是对基本用户信息进行管理。
3.2 JWT理解
JWT(Json Web Token),是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。而 JWS(JSON Web Signature)并不等于JWT,它只是JWT的一种实现,除了JWS外,还有 JWE (JSON Web Encryption) 也是 JWT 的一种实现。
4. Spring Security 授权
4.1 授权流程
这里介绍 Spring Security 的授权功能是如何实现的。
- ①首先,AuthorizationFilter 通过 SecurityContextHolder 得到 Authentication,这里通过一个Supplier来实现延迟获取。
- ②其次,AuthorizationFilter 通过 HttpServletRequest, HttpServletResponse 与 FilterChain 创建了一个FilterInvocation。
- ③下一步,将 Supplier 与 FilterInvocation【或者是HttpServletRequest】 传递给 AuthorizationManager
- ④如果授权失败,后抛出AccessDeniedException,这个异常会被 ExceptionTranslationFilter 捕获并处理。
- ⑤如果授权成功,AuthorizationFilter会继续FilterChain的正常请求流程。
4.2 授权方式
- 基于角色的授权
http
.authorizeRequests()
.antMatchers("/static/**").permitAll()
//index页面可以由user或admin访问
.antMatchers("/index").hasAnyRole("USER", "ADMIN")
//除了上面以外的所有内容,只能是admin访问
.anyRequest().hasRole("ADMIN");
- 基于权限的授权
// 基于权限的授权与角色类似,需要以`hasAnyAuthority`或`hasAuthority`进行判断
http
.authorizeRequests()
.anyRequest().hasAnyAuthority("page:index");
- 使用注解判断权限
首先需要在相应的配置类上开启;
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {}
接着就可以直接在需要添加权限验证的请求映射上添加注解,
通过添加@PreAuthorize
或@PostAuthorize
注解,可以在执行之前或之后判断权限,如果没有对应的权限或对应的角色,就无法访问页面。
@PreAuthorize("hasRole('USER')") //判断是否为user角色,只有此角色才可以访问
// @PostAuthorize("hasRole('USER')")
@RequestMapping("/index")
public String index(){
return "index";
}
5. Spring Security 实践
5.1 Security 版本
Spring Security 5.7.5
Spring Security 6.0.0 [最新]
5.2 Security 基本使用
Demo: https://github.com/PengfeiMiaoTW/Spring-Security-Demo
3、Spring Oauth2 - 分布式版本的Security框架
1. OAuth2 简介
OAuth 是一个关于授权(authorization)的开放网络标准,使得第三方应用可以使用该令牌在限定时间、限定范围访问指定资源。
1.1 基础概念
OAuth 定义了四种角色:
- “资源所有者”(resource owner):能够授予对受保护资源的访问权限的实体。当资源所有者是一个人时,它被称为终端用户。有时缩写为“RO”。
- “资源服务器”(resource server):托管受保护资源的服务器,能够接收和响应通过访问令牌对受保护资源的请求。有时缩写为“RS”。
- “客户端”(client):代表资源所有者请求受保护资源的应用程序。术语“客户端”并不指定任何特定的实现特征(例如,应用程序是在一台服务器、台式机或其他设备上运行)。
- “授权服务器”(authorization server):成功认证资源所有者并获得授权后,为客户端颁发访问令牌的服务器。有时缩写为“AS”。
1.2 协议流程
明确概念后,就可以看 OAuth2 的协议握手流程,摘自 RFC6749
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
1.3 授权模式
Oauth2.1 根据使用场景不同,分成了2种模式
- 授权码模式(authorization code)
- 客户端模式(client credentials)
授权码模式使用到了回调地址,是最为复杂的方式,通常网站中经常出现的微博,qq第三方登录,都会采用这个模式。**授权许可 **是客户端用于获得访问令牌的凭据,代表了资源所有者(对访问其受保护资源)的授权。除了这两种模式外,Oauth2.1 定义其他类型的扩展机制。
1.4 默认配置
1.5 核心模型/组件
- RegisteredClient** - **客户端实体
- RegisteredClientRepository
- OAuth2Authorization** **- 授权实体(客户端-client_credentials/用户)
- OAuth2AuthorizationService
- OAuth2AuthorizationConsent
- OAuth2AuthorizationConsentService
- OAuth2TokenContext - token上下文
- OAuth2TokenGenerator
- OAuth2TokenCustomizer
1.6 协议端点
Spring Authorization Server
(Oauth2.1 具体实现)还提供了一种实现最小配置的默认配置形式。就是通过OAuth2AuthorizationServerConfiguration
这个类。
这个类的源码路径为
org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration
OAuth2AuthorizationServerConfiguration
类中注入一个叫做authorizationServerSecurityFilterChain
的 bean,有了这个 bean,就会支持如下协议端点:
- OAuth2 Authorization endpoint(授权端点)- /oauth2/authorize
- OAuth2 Token endpoint(令牌请求端点)- /oauth2/token
- OAuth2 Token Introspection endpoint(令牌自省端点)- /oauth2/introspect
- OAuth2 Token Revocation endpoint(令牌撤销端点)- /oauth2/revoke
- OAuth2 Authorization Server Metadata endpoint(授权服务器元信息端点)
- JWK Set endpoint(JWK公钥令牌端点)- /oauth2/jwks
- OpenID Connect 1.0 Provider Configuration endpoint
- OpenID Connect 1.0 UserInfo endpoint
对于协议端点的理解:
OAuth2 在 Security 原有功能的基础上进行分布式的支持和拓展,抽象和封装出一系列的功能模块,对于每个模块暴露出指定接口形成一个端点。
这样做方便快速理解框架,通过控制端点是否开启来减少不必要过滤链的使用从而提高效率;
同时,对于端点我们可以通过在配置中重写实例快速实现定制化,提高灵活性。
2. Oauth2 实践
2.1 Oauth2 版本
1) Oauth2 协议版本
Oauth2 最新版本是 2.1版本,与 2.0版本 的区别主要如下:
OAuth 2.0 定义了四种授权方式
- 密码模式(resource owner password credentials) – OAuth2.1 删除了该模式
- 授权码模式(authorization code)
- 简化模式(implicit)-- OAuth2.1 删除了该模式
- 客户端模式(client credentials)
2) Oauth2 依赖引入
仓库名 | 项目名 | 版本号 | |
---|---|---|---|
auth-server | org.springframework.security | spring-security-oauth2-authorization-server | 0.3.1 (最新已更新到0.4.0,1.0.0) |
resoure-server | org.springframework.security | spring-security-oauth2-resource-server | 5.6.8 |
jwt | org.springframework.security | spring-security-oauth2-jose | 5.6.8 |
client | org.springframework.boot | spring-boot-starter-oauth2-client | 2.6.13 |
test | org.springframework.security | spring-security-test | 5.6.8 |
2.2 Oauth2 基本应用
简易搭建流程可以分为三个步骤:
- 配置资源服务器
- 配置授权服务器
- 配置 Spring Security
Demo: https://github.com/PengfeiMiaoTW/Spring-Security-Oauth2-Demo
2.3 Oauth2 测试
可以使用 spring security 提供的测试包,可以使用二次封装的工具 com.c4-soft.springaddons:spring-addons-oauth2-test。
1) spring-security-test
官方文档:https://docs.spring.io/spring-security/reference/6.0.0-RC1/servlet/test/index.html
@WithMockUser(username = "username", authorities = {"ROLE_USER", "ROLE_ADMIN"})
2) spring-addons-oauth2-test
开发文档:https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-oauth2-test
@WithMockAuthentication(name = "username", authorities = {"ROLE_USER", "ROLE_ADMIN"})