1. 程式人生 > 實用技巧 >Shiro教程之二Shiro.ini認證和授權

Shiro教程之二Shiro.ini認證和授權

1,Shiro.ini檔案的說明

1. ini (InitializationFile) 初始檔案.Window系統副檔名.

2. Shiro 使用時可以連線資料庫,也可以不連線資料庫.

2.1 如果不連線資料庫,可以在shiro.ini中配置靜態資料

2,Shrio.ini檔案的組成部分

1,[main] :定義全域性變數

[main]
securityManager.屬性=值            <property name=”屬性名” value=””
myobj=com.bjsxt.Obj            <bean id
=”myobj” class=”com.bjsxt.Obj” securityManager.物件屬性=$myobj   <property name=”屬性名” ref=” myobj”

2,[users] :定義使用者名稱和密碼

[users]
# 定義使用者名稱為zhangsan 密碼為zs
zhangsan=zs
# 定義使用者名稱lisi密碼為lisi同時具有role1和role2兩個角色
lisi=lisi,role1,role2

3,[roles]: 定義角色

[roles]
role1
=user:query,許可權名2 role2=許可權3,許可權4

4,[urls] : 定義哪些內建urls生效.在web應用時使用.

[urls]
#url地址=內建filter或自定義filter
# 訪問時出現/login的url必須去認證.支援authc對應的Filter
/login=authc
# 任意的url都不需要進行認證等功能.
/** = anon
# 所有的內容都必須保證使用者已經登入.
/**=user
# url abc 訪問時必須保證使用者具有role1和role2角色.
/abc=roles[“role1,role2”]
/login.html*=anon
/loginOut*=logout
/**= authc  所有URL必須認證通過之後才能放行  一般放到最後

3【掌握】Shiro.ini實現認證和授權

1,基本概念

1,身份驗證
        即在應用中誰能證明他就是他本人。一般提供如他們的身份ID 一些標識資訊來
表明他就是他本人,如提供身份證,使用者名稱/密碼來證明。
        在 shiro 中,使用者需要提供principals (身份)和credentials(證明)給shiro,從而應用能
驗證使用者身份:
2,principals 【/'prɪnsəpl】
        身份,即主體的標識屬性,可以是任何東西,如使用者名稱、郵箱等,唯一即可。
一個主體可以有多個principals,但只有一個Primary principals,一般是使用者名稱/密碼/手機號。
3,credentials 【/krə'dɛnʃlz/】
        證明/憑證,即只有主體知道的安全值,如密碼/數字證書等。
        最常見的principals和credentials組合就是使用者名稱/密碼了。接下來先進行一個基本的身份認證。

2,認證流程

其它就是使用Shrio的認證來取代我們傳統的登陸方式

3,入門程式實現認證

  1. 建立專案(引入jar包或maven依賴)

  2. 建立shiro.ini(類路徑或最後可以編譯到類路徑的目錄)

#配置使用者
[users]
zhangsan=123456
lisi=123456
wangwu=123456

  3. 寫程式碼測試 (詳見下面的登入和授權) :因為測試授權時必須登入

相關方法總結

1, 注意Subject的或取方式

2, 注意使用異常方式確定登陸是否成功

==========================

4【掌握】shiro.ini實現授權

1,授權概述

授權,也叫訪問控制,即在應用中控制誰能訪問哪些資源(如訪問頁面/編輯資料/頁面操作

等)。在授權中需瞭解的幾個關鍵物件:主體(Subject)、資源(Resource)、許可權(Permission)、

角色(Role)。

2,關鍵物件介紹

1,主體
主體,即訪問應用的使用者,在Shiro中使用Subject代表該使用者。使用者只有授權後才允許訪問相應的資源。
2,資源
在應用中使用者可以訪問的任何東西,比如訪問JSP 頁面、檢視/編輯某些資料、訪問某個業務方法、列印文字等等都是資源。使用者只要授權後才能訪問。
3,許可權
安全策略中的原子授權單位,通過許可權我們可以表示在應用中使用者有沒有操作某個資源的權力。即許可權表示在應用中使用者能不能訪問某個資源,
如:訪問使用者列表頁面檢視
/新增/修改/刪除使用者資料(即很多時候都是CRUD(增查改刪)式許可權控制)列印文件等等。。。 4,角色 角色代表了操作集合,可以理解為許可權的集合,一般情況下我們會賦予使用者角色而不是許可權,即這樣使用者可以擁有一組許可權,賦予許可權時比較方便。
典型的如:專案經理、技術總監、CTO、開發工程師等都是角色,不同的角色擁有一組不同的許可權。

3,授權流程

4,相關方法說明

1 subject.hasRole(“”); 判斷是否有角色

2 subject.hashRoles(List);分別判斷使用者是否具有List中每個內容

3 subject.hasAllRoles(Collection);返回boolean,要求引數中所有角色使用者都需要具有.

4 subject.isPermitted(“”);判斷是否具有許可權.

5,修改shiro.ini

#配置使用者
[users]
zhangsan=123456,role1
lisi=123456,role2,role4
wangwu=123456,role3
zhaoliu=123456,role4

#配置角色和許可權
[roles]
role1=user:query,user:add,user:update,user:delete,user:export
role2=user:query
role3=user:query,user:add
role4=user:query,user:export

6,許可權識別符號號規則

許可權識別符號號規則:資源:操作:例項(中間使用半形:分隔)
user:create:01 表示對使用者資源的01例項進行create操作。
user:create:表示對使用者資源進行create操作,相當於user:create:*,對所有使用者資源例項進行create操作。
user:*:01 表示對使用者資源例項01進行所有操作。

7,測試程式碼 (認證和授權一塊測試)

package com.cc8w.test;

import com.cc8w.shiro.ShiroRealm;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Arrays;

/**
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TestShiro {
    private static Logger logger = Logger.getLogger(TestShiro.class);

    @Autowired
    private ShiroRealm shiroRealm;

    /**
     * 1.獲取安全管理器
     * 2.獲取使用者
     * 3.使用者登入驗證
     * 4.許可權管理
     * 5.角色管理
     * 6.session
     */
    public static void main(String[] args) {
        TestShiro ts = new TestShiro();
        ts.testAuth();


    }

    //一,登入測試(基於ini檔案,註釋掉shiro的main區域,因為此區域配置了非ini檔案[自定義Realm]的設定)
    @Test
    public void testlogin(){
        //1.建立一個安全管理器的工廠
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2.在工廠中獲取安全管理器
        SecurityManager securityManager = factory.getInstance();
        //3.將securityManager繫結到執行環境
        SecurityUtils.setSecurityManager(securityManager);
        //4.獲取Subject物件(將要登入的使用者)
        Subject subject = SecurityUtils.getSubject();
        //5.獲取要登入使用者的token,客戶端傳遞過來的使用者名稱和密碼
        String username = "zhangsan",password="123456";
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);

        try{
            subject.login(token);
            logger.info("登入了");

        }catch (IncorrectCredentialsException  e ){
            logger.info("密碼不正確");
            logger.info(e);
        }catch (UnknownAccountException e) {
            System.out.println("沒有這個帳號");
        }catch (AuthenticationException e) {
            e.printStackTrace();
        }

        //如果登入成功了,可以獲取subject中各種狀態了
        Boolean isAuth = subject.isAuthenticated();
        logger.info(isAuth);
        try {
            subject.checkRole("roles");
        }catch (UnauthenticatedException e){
            logger.info("沒有這個角色");
            e.printStackTrace();
        }

    }
    //二.授權驗證(基於ini檔案,註釋掉shiro的main區域,因為此區域配置了非ini檔案[自定義Realm]的設定)
    @Test
    public void testAuth(){
        String username = "zhangsan",password="123456";
        //1.建立securityManager工廠SecurityManager JDK也有這個類,在java.lang包,注意不要使用jdk裡面的類
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2,從工廠中獲取SecurityManager
        SecurityManager securityManager = factory.getInstance();
        //3,把當前的SecurityManager繫結到當前執行緒中
        SecurityUtils.setSecurityManager(securityManager);
        //4,取出當前的Subject
        Subject subject = SecurityUtils.getSubject();

        //5.建立token用於認證 客戶端傳遞過來的使用者名稱和密碼
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        //6.登入認證
        try{
            subject.login(token);
            System.out.println("登入成功");
        }catch (IncorrectCredentialsException  e){
            System.out.println("密碼不正確");
        }catch (UnknownAccountException e){
            System.out.println("無此賬號");
        }catch (AuthenticationException e) {
            e.printStackTrace();
        }
        System.out.println("認證狀態:"+subject.isAuthenticated());

        //7.授權 基於角色授權 基於資源的授權

        //7.1 基於角色授權
        boolean isRole1 = subject.hasRole("role1");
        System.out.println("這是授權單個: "+isRole1);

        boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3"));
        System.out.println("這是多個授權:" + hasAllRoles);

        // 使用check方法進行授權,如果授權不通過會丟擲異常
        // subject.checkRole("role13");


        // 7.2 基於資源的授權
        // isPermitted傳入許可權識別符號
        boolean isPermitted = subject.isPermitted("user:query");
        System.out.println("單個許可權判斷user:query->"+isPermitted);
        boolean isPermittedAll = subject.isPermittedAll("user:query","user:add","user:del");
        System.out.println("多個許可權判斷"+isPermitted);

        // 使用check方法進行授權,如果授權不通過會丟擲異常
        try{
            subject.checkPermission("items:create:1");
        }catch (UnauthorizedException e){
            // e.printStackTrace();
            System.out.println("沒有這個許可權");
        }

    }


}