- [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 } ```