日常提交
This commit is contained in:
73
spring/Apache Shiro/Apache Shiro.md
Normal file
73
spring/Apache Shiro/Apache Shiro.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Apache Shiro
|
||||
## Shiro简介
|
||||
Shiro是一个简单易用且功能强大的Java安全框架,用于实现认证、授权、加密、session管理等场景,并且Shiro可以被用于任何应用,包括命令行应用、移动应用、大型web应用或是企业应用。
|
||||
Shiro在如下方面提供Security API:
|
||||
- Authentication:为用户提供身份认证
|
||||
- Authorization:为应用提供用户的访问控制
|
||||
- 加密:避免应用数据处于明文状态
|
||||
- session管理:每个用户的时间敏感状态
|
||||
## Shiro中常用的概念
|
||||
Shiro框架的结构主要分为三个部分:Subject、SecurityManager、Realms
|
||||
### Subject
|
||||
Subject:Subject是一个安全术语,通常意味着当前执行的用户。
|
||||
```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。
|
||||
|
||||
对每个应用中,只存在一个SecurityManager,SecurityManager是应用范围内的单例。默认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来实现权限认证可能会存在问题,
|
||||
|
||||
Reference in New Issue
Block a user