Apache Shiro 權限框架

分享一個視屏教程集合 http://www.tudou.com/home/konghao/item數據庫

1.Shiro apache

  Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、受權、密碼學和會話管理。使用Shiro的易於理解的API,您能夠快速、輕鬆地得到任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序,能夠和Spring無縫結合.關鍵步驟須要開發實現.編程

2.主要功能 安全

Authentication   認證

Authorization   受權

Cryptography   加密

Session Management   Session 管理

Web Integration   Web集成

Integrations  和其餘集成

  三個核心組件:Subject, SecurityManager 和 Realms[域].
  Subject:即「當前操做用戶」。可是,在Shiro中,Subject這一律念並不只僅指人,也能夠是第三方進程、後臺賬戶(Daemon Account)或其餘相似事物。它僅僅意味着「當前跟軟件交互的東西」。但考慮到大多數目的和用途,能夠把它認爲是Shiro的「用戶」概念。
  Subject:表明了當前用戶的安全操做,SecurityManager則管理全部用戶的安全操做,Current User。
  SecurityManager:它是Shiro框架的核心,管理全部的Subject
  Realm:Access your security data, Realm充當了Shiro與應用安全數據間的「橋樑」或者「鏈接器」。也就是說,當對用戶執行認證(登陸)和受權(訪問控制)驗證時,Shiro會從應用配置的Realm中查找用戶及其權限信息。
  從這個意義上講,Realm實質上是一個安全相關的DAO:它封裝了數據源的鏈接細節,並在須要時將相關數據提供給Shiro。當配置Shiro時,你必須至少指定一個Realm,用於認證和(或)受權。
  Shiro內置了能夠鏈接大量安全數據源(又名目錄)的Realm,如LDAP、關係數據庫(JDBC)、相似ini的文本配置資源以及屬性文件等。若是缺省的Realm不能知足需求,你還能夠插入表明自定義數據源的本身的Realm。【百度百科】
 
3.POM.xml
<!-- 添加Apache Shiro 依賴關係 -->
<dependency>  
        <groupId>org.apache.shiro</groupId>  
        <artifactId>shiro-core</artifactId>  
        <version>1.2.2</version>  
 </dependency>  

4.受權  網絡

  也叫訪問控制,在應用中控制誰能訪問哪些資源(如訪問頁面/編輯數據/頁面操做等)。在受權中需瞭解的幾個關鍵對象:主體(Subject)、資源(Resource)、權限(Permission)、角色(Role)。框架

5.主體【Subject】
數據庫設計

  主體,即訪問應用的用戶,在Shiro中使用Subject表明該用戶。用戶只有受權後才容許訪問相應的資源。函數

6.資源【Resource】
測試

  在應用中用戶能夠訪問的任何東西,好比訪問JSP頁面、查看/編輯某些數據、訪問某個業務方法、打印文本等等都是資源。用戶只要受權後才能訪問。ui

7.權限

  安全策略中的原子受權單位,經過權限咱們能夠表示在應用中用戶有沒有操做某個資源的權力。即權限表示在應用中用戶能不能訪問某個資源,如:

  訪問用戶列表頁面

  查看/新增/修改/刪除用戶數據(即不少時候都是CRUD(增查改刪)式權限控制)

  打印文檔等等。。。

  如上能夠看出,權限表明了用戶有沒有操做某個資源的權利,即反映在某個資源上的操做允不容許,不反映誰去執行這個操做。因此後續還須要把權限賦予給用戶,即定義哪一個用戶容許在某個資源上作什麼操做(權限),Shiro不會去作這件事情,而是由實現人員提供。

8.角色【Role】

  角色表明了操做集合,能夠理解爲權限的集合,通常狀況下咱們會賦予用戶角色而不是權限,即這樣用戶能夠擁有一組權限,賦予權限時比較方便。典型的如:項目經理、技術總監、CTO、開發工程師等都是角色,不一樣的角色擁有一組不一樣的權限。

  隱式角色:

  顯式角色:

    請baidu搜索「RBAC」和「RBAC新解」分別瞭解「基於角色的訪問控制」「基於資源的訪問控制(Resource-Based Access Control)」。

9.Shiro 受權方式

  Shiro支持三種方式受權

  (1)編程式

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(「admin」)) {  
    //有權限  
} else {  
    //無權限  
}   

  (2)註解式:經過在執行的Java方法上放置相應的註解完成,沒有權限將拋出相應的異常;

@RequiresRoles("admin")  
public void hello() {  
    //有權限  
}   

  (3)JSP/GSP標籤:在JSP/GSP頁面經過相應的標籤完成

<shiro:hasRole name="admin">  
<!— 有權限 —>  
</shiro:hasRole>   

受權

  (1)基於角色的訪問控制(隱式角色)

    在ini配置文件配置用戶擁有的角色(shiro-role.ini) 

[users]  
zhang=123,role1,role2  
wang=123,role1 

  規則即:「用戶名=密碼,角色1,角色2」,若是須要在應用中判斷用戶是否有相應角色,就須要在相應的Realm中返回角色信息,也就是說Shiro不負責維護用戶-角色信息,須要應用提供,Shiro只是提供相應的接口方便驗證

  測試用例

@Test  
public void testHasRole() {  
    login("classpath:shiro-role.ini", "zhang", "123");  
    //判斷擁有角色:role1  
    Assert.assertTrue(subject().hasRole("role1"));  
    //判斷擁有角色:role1 and role2  
    Assert.assertTrue(subject().hasAllRoles(Arrays.asList("role1", "role2")));  
    //判斷擁有角色:role1 and role2 and !role3  
    boolean[] result = subject().hasRoles(Arrays.asList("role1", "role2", "role3"));  
    Assert.assertEquals(true, result[0]);  
    Assert.assertEquals(true, result[1]);  
    Assert.assertEquals(false, result[2]);  
}   

  Shiro提供了hasRole/hasRole用於判斷用戶是否擁有某個角色/某些權限;可是沒有提供如hashAnyRole用於判斷是否有某些權限中的某一個。  

@Test(expected = UnauthorizedException.class)  
public void testCheckRole() {  
    login("classpath:shiro-role.ini", "zhang", "123");  
    //斷言擁有角色:role1  
    subject().checkRole("role1");  
    //斷言擁有角色:role1 and role3 失敗拋出異常  
    subject().checkRoles("role1", "role3");  
}   

(2)基於資源的訪問控制(顯式角色)

  在ini配置文件配置用戶擁有的角色及角色-權限關係(shiro-permission.ini)

[users]  
zhang=123,role1,role2  
wang=123,role1  
[roles]  
role1=user:create,user:update  
role2=user:create,user:delete   

  規則:「用戶名=密碼,角色1,角色2」「角色=權限1,權限2」,即首先根據用戶名找到角色,而後根據角色再找到權限;即角色是權限集合;Shiro一樣不進行權限的維護,須要咱們經過Realm返回相應的權限信息。只須要維護「用戶——角色」之間的關係便可。

  測試用例

@Test  
public void testIsPermitted() {  
    login("classpath:shiro-permission.ini", "zhang", "123");  
    //判斷擁有權限:user:create  
    Assert.assertTrue(subject().isPermitted("user:create"));  
    //判斷擁有權限:user:update and user:delete  
    Assert.assertTrue(subject().isPermittedAll("user:update", "user:delete"));  
    //判斷沒有權限:user:view  
    Assert.assertFalse(subject().isPermitted("user:view"));  
}   
@Test(expected = UnauthorizedException.class)  
public void testCheckPermission () {  
    login("classpath:shiro-permission.ini", "zhang", "123");  
    //斷言擁有權限:user:create  
    subject().checkPermission("user:create");  
    //斷言擁有權限:user:delete and user:update  
    subject().checkPermissions("user:delete", "user:update");  
    //斷言擁有權限:user:view 失敗拋出異常  
    subject().checkPermissions("user:view");  
}   

  失敗的狀況下會拋出 UnauthorizedException 異常.

  Subject subject = SecurityUtils.getSubject();

案例筆記:

 

權限數據庫設計(PS:儘可能不要涉及外鍵,管理起來有時候會比較麻煩):

表:User(用戶) Role(角色) UserRole(用戶角色對應關係) Resource(資源) RoleResource(角色資源)

User(id username userpwd nickname status)   //status標註用戶帳號是否停用或者被鎖定;

Role(id name)

Resource(id name permission url)

RoleResource(id roleId resId)

UserRole(id userId roleId)

Dao設計:繼承IBaseDao

IuserDao: 用戶接口

public list<User> listAllUsers();//查詢全部用戶

public list<User> listUsersByRole(int roleId);//根據角色取出全部用戶

public User loadByUserName(string username);//根據用戶獲得用戶

IRoleDao: 角色接口

public list<Role> listRoles();//查詢全部的角色

public list<Role> listUserRole();//查詢某個用戶全部的角色

pubic UserRole loadUserRole(int userId,int RoleId);

public void addUserRole(int userId,int RoleId);

public void deleteUserRole(int UserId,int RoleId);

public void deleteUserRole(int UserId);//刪除某個用戶的全部角色

public List<Resource> listRoleResources(int roleId);//根據角色Id添加角色能夠訪問的資源

public void addRoleResource(int RoleId,int resId);

public void deleteRoleResource(int roleId,int resId);

public RoleResource loadRoleResource(int roleId,int resId); //獲取角色資源對象

IResourceDao: 資源接口

public List<Resource> listResource();

 02 實現Service層:

IUserService     IRoleService   IRoleResource

shiro.Kit包下面添加密碼加密函數  

static String md5(String password,String salt) {

 String p = null;

   p = new Md5Hash(password,salt).toHex();

   return P;

}

03 Junit 實現對Service層測試;