94 lines
4.8 KiB
Markdown
94 lines
4.8 KiB
Markdown
- [Apache Shiro Authorization](#apache-shiro-authorization)
|
||
- [Authorization简介](#authorization简介)
|
||
- [Authorization的核心元素](#authorization的核心元素)
|
||
- [Permission](#permission)
|
||
- [权限粒度级别](#权限粒度级别)
|
||
- [Roles](#roles)
|
||
- [Role分类](#role分类)
|
||
- [User](#user)
|
||
- [在Apache Shiro中实行Authorization](#在apache-shiro中实行authorization)
|
||
- [通过java code实现authorization](#通过java-code实现authorization)
|
||
- [基于String的权限鉴定](#基于string的权限鉴定)
|
||
- [通过注解实现Authorization](#通过注解实现authorization)
|
||
|
||
# Apache Shiro Authorization
|
||
## Authorization简介
|
||
Authorization(访问控制),分配访问某资源的特定权限。
|
||
## Authorization的核心元素
|
||
### Permission
|
||
Permission是最原子级别的安全策略,用来控制用户与应用进行交互时可以执行哪些操作。**格式良好的permission描述了资源的类型和与该资源交互时可以执行的操作。**
|
||
对于与数据相关的资源,权限通常有create、read、update、delete(CRUD)。
|
||
#### 权限粒度级别
|
||
在Shiro中,可以在任何粒度对permission进行定义。如下是permission粒度的一些定义:
|
||
1. Resource级别:该级别是最广泛和最容易构建的粒度级别,在该级别用户可以对资源执行特定的操作。**在Resource级别,该资源类型被指定,但是没有限制用户操作特定的资源实例(即用户可以对该Resource类型的所有实例进行操作)**
|
||
2. Instance级别:该级别限定了Permission可以操作的Resource Instance,在该级别用户只能够对特定的Resource实例进行操作。
|
||
3. Attribute级别:该级别比限定了Permission可以操作Resouce类型或Resource实例的某个属性
|
||
### Roles
|
||
Roles是一个Permission的集合,用于简化权限和用户管理过程。用户可以被授予特定的角色来获得操作某些资源的权限。
|
||
#### Role分类
|
||
1. Role不实际关联具体的Permission,当你具有banker的角色时,其角色隐含你可以对账户进行操作的权限;当你具有waiter的角色时,默认可以对厨房的door进行open/close操作
|
||
2. Role实际关联具体的Permission,在该情况下Role即为一系列Permission的集合,你可以对银行账号进行create、delete操作,因为操作银行账号是你已分配的admin角色的一个下属权限
|
||
### User
|
||
在Shiro中,User即是一个Subject实例。在Shiro中,Subject可以是任何与系统进行交互的主体,可以是浏览器、客户端、crond定时任务等。
|
||
## 在Apache Shiro中实行Authorization
|
||
在Apache Shiro中,Authorization可以通过如下方式执行:
|
||
1. 通过代码实现:即在java程序中通过代码实现访问控制
|
||
2. jdk注解:可以在你的方法上加上authorization注解
|
||
3. jsp/gsp taglibs
|
||
### 通过java code实现authorization
|
||
可以通过如下代码进行角色鉴定:
|
||
```java
|
||
//get the current Subject
|
||
Subject currentUser = SecurityUtils.getSubject();
|
||
|
||
if (currentUser.hasRole("administrator")) {
|
||
//show a special button
|
||
} else {
|
||
//don’t show the button?)
|
||
}
|
||
```
|
||
可以通过如下代码实现对权限的鉴定操作:
|
||
```java
|
||
Subject currentUser = SecurityUtils.getSubject();
|
||
|
||
Permission printPermission = new PrinterPermission("laserjet3000n","print");
|
||
|
||
If (currentUser.isPermitted(printPermission)) {
|
||
//do one thing (show the print button?)
|
||
} else {
|
||
//don’t show the button?
|
||
}
|
||
```
|
||
#### 基于String的权限鉴定
|
||
如果不想构造Permission对象,可以通过构造一个字符串来代表权限。该字符串可以是任何格式,只要你的Realm能够识别该格式并且与权限进行交互。
|
||
```java
|
||
String perm = "printer:print:laserjet4400n";
|
||
|
||
if(currentUser.isPermitted(perm)){
|
||
//show the print button?
|
||
} else {
|
||
//don’t show the button?
|
||
}
|
||
```
|
||
### 通过注解实现Authorization
|
||
可以通过java注解来实现Authorization过程,**在使用注解之前,必须先开启aop**。
|
||
如果在执行openAccount之前,当前Subject必须拥有account:create权限,那么可以通过如下方式来实现权限鉴定。如果当前用户未被直接授予或通过role间接授予该权限,那么会抛出AuthorizationException异常。
|
||
```java
|
||
//Will throw an AuthorizationException if none
|
||
//of the caller’s roles imply the Account
|
||
//'create' permission
|
||
@RequiresPermissions("account:create")
|
||
public void openAccount( Account acct ) {
|
||
//create the account
|
||
}
|
||
```
|
||
如果要在执行方法之前进行角色校验,可以通过如下方式加上注解达到预期功能。
|
||
```java
|
||
//Throws an AuthorizationException if the caller
|
||
//doesn’t have the ‘teller’ role:
|
||
@RequiresRoles( "teller" )
|
||
public void openAccount( Account acct ) {
|
||
//do something in here that only a teller
|
||
//should do
|
||
}
|
||
``` |