81 lines
4.5 KiB
Markdown
81 lines
4.5 KiB
Markdown
# Apache Shiro Authentication
|
||
## Apache Shiro Authentication简介
|
||
Authentication是一个对用户进行身份认证的过程,在认证过程中用户需要向应用提供用于证明用户的凭据。
|
||
## Apache Authentication概念
|
||
### subject
|
||
在应用的角度,subject即是一个用户
|
||
### principals
|
||
主体,用于标识一个用户,可以是username、social security nubmer等
|
||
### credentials
|
||
凭据,在用户认证过程中用于认证用户的身份,可以是密码、生物识别数据(如指纹、面容等)
|
||
### realms
|
||
专用于security的dao对象,用于和后端的datasource进行沟通。
|
||
## Shiro Authentication过程
|
||
### Shiro框架的Authentication过程
|
||
1. 收集用户的principals和credentials
|
||
2. 向应用的认证系统提交用户的principals和credentials
|
||
3. 认证结束之后,根据认证结果允许访问、重试访问请求或者阻塞访问
|
||
### 收集用户的principals和credentials
|
||
可以通过UsernamePasswordToken来存储用户提交的username和password,并可以调用UsernamePasswordToken.rememberMe方法来启用Shiro的“remember-me”功能。
|
||
```java
|
||
//Example using most common scenario:
|
||
//String username and password. Acquire in
|
||
//system-specific manner (HTTP request, GUI, etc)
|
||
UsernamePasswordToken token = new UsernamePasswordToken( username, password );
|
||
|
||
//”Remember Me” built-in, just do this:
|
||
token.setRememberMe(true);
|
||
```
|
||
### 将收集的principals和credentials提交给认证系统
|
||
在收集完用户的principals和credentials之后,需要将其提交给应用的认证系统。
|
||
在Shiro中,代表认证系统的是Realm,其从存放安全数据的datasource中获取数据,并且对用户提交的principals和credentials进行校验。
|
||
在Shiro中,该过程用如下代码表示:
|
||
```java
|
||
//With most of Shiro, you'll always want to make sure you're working with the currently
|
||
//executing user, referred to as the subject
|
||
Subject currentUser = SecurityUtils.getSubject();
|
||
|
||
//Authenticate the subject by passing
|
||
//the user name and password token
|
||
//into the login method
|
||
currentUser.login(token);
|
||
```
|
||
> 在Shiro中,subject可以被看做是用户,**在当前执行的线程中永远有一个subject与其相关联。**
|
||
> **可以通过SecurityUtils.getSubject()方法来获取当前执行线程相关联的subject。**
|
||
|
||
> 在获取当前执行线程关联subject之后,需要对当前subject进行身份认证,通过subject.login(token)来对用户提交的principals和credentials进行Authentication
|
||
|
||
### 身份认证后对访问进行allow/retry authentication/block
|
||
在调用subject.login(token)之后,如果身份认证成功,用户将在seesion的生命周期内维持他们的identity。但是如果身份认证失败,可以为抛出的异常指定不同的异常处理逻辑来定义登录失败之后的行为。
|
||
```java
|
||
try {
|
||
currentUser.login(token);
|
||
} catch ( UnknownAccountException uae ) { ...
|
||
} catch ( IncorrectCredentialsException ice ) { ...
|
||
} catch ( LockedAccountException lae ) { ...
|
||
} catch ( ExcessiveAttemptsException eae ) { ...
|
||
} ... your own ...
|
||
} catch ( AuthenticationException ae ) {
|
||
//unexpected error?
|
||
}
|
||
//No problems, show authenticated view…
|
||
```
|
||
## rememberMe支持
|
||
Apache Shiro除了正常的Authentication流程外,还支持rememberMe功能。
|
||
Shiro中Subject对象拥有两个方法,isRemembered()和isAuthenticated()。
|
||
> - 一个remembered subject,其identity和principals自上次session成功认证后就被记住
|
||
> - 一个authenticated subject,其identity只在本次会话中有效
|
||
|
||
### remembered和authenticated的区别
|
||
在Shiro中,一个remembered subject并不代表该subject已经被authenticated。如果一个subject被remembered,仅仅会向系统提示该subject可能是系统的某个用户,但是不会对subject的身份提供保证。但是如果subject被authenticated,该subject的identity在当前会话中已经被认证。
|
||
> 故而,isRemembered校验可以用来执行一些非敏感的操作,如用户自定义界面视图等。但是,敏感性操作如金额信息和变动操作等,必须通过isAuthenticated校验而不是isRemembered校验,敏感性操作的用户身份必须得到认证。
|
||
|
||
## logging out
|
||
在Shiro中,登出操作可以通过如下代码实现
|
||
```java
|
||
currentUser.logout(); //removes all identifying information and invalidates their session too.
|
||
```
|
||
当执行登出操作时,Shiro会关闭当前session,并且会移除当前subject的任何identity。如果在web环境中使用rememberMe,logout默认会从浏览器中删除rememberMe cookie。
|
||
|
||
|