Files
rikako-note/spring/Apache Shiro/Apache Shiro.md
wu xiangkai ce79102b7f 日常提交
2022-10-13 18:08:54 +08:00

74 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Apache Shiro
## Shiro简介
Shiro是一个简单易用且功能强大的Java安全框架用于实现认证、授权、加密、session管理等场景并且Shiro可以被用于任何应用包括命令行应用、移动应用、大型web应用或是企业应用。
Shiro在如下方面提供Security API
- Authentication为用户提供身份认证
- Authorization为应用提供用户的访问控制
- 加密:避免应用数据处于明文状态
- session管理每个用户的时间敏感状态
## Shiro中常用的概念
Shiro框架的结构主要分为三个部分Subject、SecurityManager、Realms
### Subject
SubjectSubject是一个安全术语通常意味着当前执行的用户。
```java
import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
// 获取Subject对象
Subject currentUser = SecurityUtils.getSubject();
```
### SecurityManager
相对于Subject代表对于当前用户的安全操作SecurityManager代表对所有用户的安全操作。SecurityManager是Shiro结构的核心其由多个security component嵌套组成。
> 一旦SecurityManager和其嵌套的security component被配置完成那么用户将不再使用SecurityManager而是调用Subject API。
对每个应用中只存在一个SecurityManagerSecurityManager是应用范围内的单例。默认SecurityManager的实现是POJO可以通过java代码、Spring xml、yaml、properties等方式来进行配置。
### realms
realms是shiro和应用中security data如账户登录的登录数据或授权管理的权限数据之间的连接器。当Shiro和security data进行交互时shiro会从配置好的一个或者多个realm中获取security data。
> 在上述情况下realm类似于一个安全数据的特定DAO其封装了到数据源连接的详细信息并且为Shiro提供安全数据。当配置Shiro时必须指定至少一个Realm用于身份认证和权限认证。
> Shiro提供了开箱即用的Realm来连接很多种security data source比如LDAP关系型数据库JDBC基于文本配置的data source例如ini或properties文件。可以通过自定义Realm的实现来访问自定义的data source如果默认的Realm不能满足需求。
## Authentication
认证过程用于认证用户的身份。认证过程的主要流程如下:
1. 收集用户的身份标识信息通常称之为主体principal和身份证明通常称之为凭据credentials
2. 向系统提交主体和凭据
3. 如果提交的凭据和系统中该主体对应的凭据相同,那么该用户会被认为是“通过认证的”。如果提交的凭据不符,那么该用户会被认为是“认证失败的”。
```java
// 认证流程代码
//1. Acquire submitted principals and credentials:
AuthenticationToken token =
new UsernamePasswordToken(username, password);
//2. Get the current Subject:
Subject currentUser = SecurityUtils.getSubject();
//3. Login:
currentUser.login(token);
```
当login方法被调用时SecurityMananger将会收到AuthenticationToken并且将其分配到一个或多个已经配置好的Realm中并且让每个Realm执行需要的认证流程。每个Reaml都能对提交的AuthenticaitonToken做出处理。
如果认证过程失败那么会抛出AuthenticationException可以通过捕获该异常来对失败的认证进行处理。
```java
//3. Login:
try {
currentUser.login(token);
} catch (IncorrectCredentialsException ice) {
} catch (LockedAccountException lae) {
}
catch (AuthenticationException ae) {
}
```
**当用户通过身份认证之后,其被认为是“通过身份认证的”,并且被允许使用应用。但是,通过身份认证并不意味着可以在系统中执行任何操作。通过授权,可以决定用户能够在系统中执行哪些操作。**
## Authorization
Authorization的实质是访问控制通常用于控制用户在系统中能够使用哪些资源。大多数情况下可以通过role或permission等形式来实现访问控制用户通过分配给他们的角色或者权限来执行操作。通过检查用户的role或者permission系统可以决定将哪些功能暴露给用户。
```java
// 通过如下代码Subject可以实现对用户的role检测
if ( subject.hasRole(administrator) ) {
//show the Create User button
} else {
//grey-out the button?
}
```
> 通过role来实现权限认证可能会存在问题