Shiro許可權框架使用總結

来源:http://www.cnblogs.com/xrmqbl/archive/2016/03/07/5250172.html
-Advertisement-
Play Games

我們首先瞭解下什麼是shiro ,Shiro 是 JAVA 世界中新近出現的許可權框架,較之 JAAS 和 Spring Security,Shiro 在保持強大功能的同時,還在簡單性和靈活性方面擁有巨大優勢 Shiro 是一個強大而靈活的開源安全框架,能夠非常清晰的處理認證、授權、管理會話以及密碼加


我們首先瞭解下什麼是shiro ,Shiro 是 JAVA 世界中新近出現的許可權框架,較之 JAAS 和 Spring Security,Shiro 在保持強大功能的同時,還在簡單性和靈活性方面擁有巨大優勢

 

Shiro 是一個強大而靈活的開源安全框架,能夠非常清晰的處理認證、授權、管理會話以及密碼加密。如下是它所具有的特點:

  1. 易於理解的 Java Security API;
  2. 簡單的身份認證(登錄),支持多種數據源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
  3. 對角色的簡單的簽權(訪問控制),支持細粒度的簽權;
  4. 支持一級緩存,以提升應用程式的性能;
  5. 內置的基於 POJO 企業會話管理,適用於 Web 以及非 Web 的環境;
  6. 異構客戶端會話訪問;
  7. 非常簡單的加密 API;
  8. 不跟任何的框架或者容器捆綁,可以獨立運行。

Shiro 主要有四個組件

 

  1. SecurityManager

    典型的 Facade,Shiro 通過它對外提供安全管理的各種服務。

  2. Authenticator

    對“Who are you ?”進行核實。通常涉及用戶名和密碼。

    這 個組件負責收集 principals 和 credentials,並將它們提交給應用系統。如果提交的 credentials 跟應用系統中提供的 credentials 吻合,就能夠繼續訪問,否則需要重新提交 principals 和 credentials,或者直接終止訪問。

  3. Authorizer

    身 份份驗證通過後,由這個組件對登錄人員進行訪問控制的篩查,比如“who can do what”, 或者“who can do which actions”。Shiro 採用“基於 Realm”的方法,即用戶(又稱 Subject)、用戶組、角色和 permission 的聚合體。

  4. Session Manager

    這個組件保證了異構客戶端的訪問,配置簡單。它是基於 POJO/J2SE 的,不跟任何的客戶端或者協議綁定。

 

Shiro 的認證和簽權可以通過 JDBC、LDAP 或者 Active Directory 來訪問資料庫、目錄伺服器或者 Active Directory 中的人員以及認證 / 簽權信息。SessionManager 通過會話 DAO 可以將會話保存在 cache 中,或者固化到資料庫或文件系統中。

 

簡介

apache shiro 是一個功能強大易於使用Java安全框架,為開發人員提供一個直觀而全面的解決方案認證,授權加密會話管理

在實際應用中實現了應用程式的安全管理的各個方面。

 

shiro的功能

 

 

apache shiro能做什麼?

支持認證跨一個或多個數據源(LDAP,JDBC,kerberos身份等)

執行授權,基於角色的細粒度的許可權控制。

增強的緩存的支持。

支持web或者非web環境,可以在任何單點登錄(SSO)或集群分散式會話中使用。

主要功能是:認證,授權,會話管理和加密。

下載並且使用

1,確保系統內安裝JDK1.5+和maven2.2+。

2,到shiro主頁下載shiro.

3,解壓縮

unzip shiro-root-1.1.0-source-release.zip

4,進入到quickstart目錄

cd shiro-root-1.1.0/samples/quickstart

5,運行quickstart

 mvn compile exec:java

執行完成如下圖:

Quickstart.java

 // get the currently executing user:
 Subject currentUser = SecurityUtils.getSubject();

使用SecurityUtils.getSubject(),我們可以得到當前正在執行的主題。

得到主題之後,你可以得到他對應的會話信息

 // Do some stuff with a Session (no need for a web or EJB container!!!)
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
        }

你可以得到http的session信息,也可以在非web環境中使用,得到相對應的會話信息。

如果在web應用程式中部署應用,預設情況下,應用將以HttpSession為基礎。在企業級應用中,你在多個應用中可以使用相同的API,無論部署環境。而且使用任何客戶端技術你都可以共用會話數據。

接下來判斷登錄信息

 // let's login the current user so we can check against roles and permissions:
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            try {
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

如果正確可以向下執行,如果不正確,就會對不同的業務進行處理。

比如用戶名不正確,密碼不正確,用戶被鎖定的異常,當然也可以使用自定義拋出的異常。

如果登錄成功,那麼下一步可以做什麼呢?

提示當前用戶:

//say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

接著測試是否還有其它角色

//test a role:
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

接著測試是否有特定的許可權

//test a typed permission (not instance-level)
        if (currentUser.isPermitted("lightsaber:weild")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

接著驗證一個非常強大的實例級許可權

 //a (very powerful) Instance Level permission:
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

最後是使用程式註銷:

//all done - log out!
        currentUser.logout();

認證就是用戶確認身份的過程,確認登錄的用戶身份能夠操作的內容。

使用shiro認證分為以下幾個步驟:

1,得到主體的認證和憑據。

view sourceprint?
// let's login the current user so we can check against roles and permissions:
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);

2,提交認證和憑據給身份驗證系統。

view sourceprint?
Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);

3,判斷是否允許訪問,重試認證或者阻止訪問。

view sourceprint?
try {
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }

其中Remember Me的功能包括兩個方法,一個是

isRemembered

boolean isRemembered()
非匿名登錄的用戶可以記住上次使用的主題的信息。

isAuthenticated

boolean isAuthenticated()
在此期間需要使用有效的憑據登錄系統,否則值為false.
 
授權操作
授權的例子就是是否可以訪問某個頁面,可以操作某個按鈕,是否可以編緝對應的數據等。
如何在shiro中使用授權
1,使用編程方式
判斷是否有管理員角色
view sourceprint?
if (currentUser.hasRole("admin")) {
判斷用戶是否有列印的許可權
view sourceprint?
Permission printPermission = new PrinterPermission(“laserjet3000n”,“print”);
If (currentUser.isPermitted(printPermission)) {
    //do one thing (show the print button?)‏
} else {
    //don’t show the button?
}

也可以使用字元串的方式驗證

view sourceprint?
String perm = “printer:print:laserjet4400n”;
  
if(currentUser.isPermitted(perm)){
    //show the print button?
} else {
    //don’t show the button?
}

 

2,使用註釋方式
 判斷用戶是否有 創建賬戶許可權
view sourceprint?
//Will throw an AuthorizationException if none
//of the caller’s roles imply the Account 
//'create' permission\u000B
@RequiresPermissions(“account:create”)‏
public void openAccount( Account acct ) { 
    //create the account
}
判斷用戶角色,如果符合角色,可以使用對應方法
view sourceprint?
//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
}
3,使用jsp taglib
 判斷用戶是否有管理許可權
view sourceprint?
<%@ taglib prefix=“shiro” uri=http://shiro.apache.org/tags %>
<html>
<body>
    <shiro:hasPermission name=“users:manage”>
        <a href=“manageUsers.jsp”>
            Click here to manage users
        </a>
    </shiro:hasPermission>
    <shiro:lacksPermission name=“users:manage”>
        No user management for you!
    </shiro:lacksPermission>
</body>
</html>
 
從高的級別來看shiro:
看一下官方的圖

應用程式調用subject(主題),主題可以是一個用戶也可以是與系統交互的另一個系統,主題綁定shiro的許可權管 理,SecurityManager(安全管理),它控制與有與主題相關的安全操作。Realm(橋梁)它是安全與數據之間的橋,它封裝了比如DAO的配 置信息,可以指定連接的數據源,也可使用其它的認證方式,如LDAP等。

然後看一下詳細的架構圖:

Subject (org.apache.shiro.subject.Subject)

主題:與系統交互的第三方如(用戶,cron服務,第三方應用)等。

SecurityManager (org.apache.shiro.mgt.SecurityManager)

shiro系統的核心,協調主題使用的操作,驗證,配置等。

Authenticator (org.apache.shiro.authc.Authenticator)

身份驗證組件,對企圖登錄系統的用戶進行身份的驗證。其中包含一個Authentication Strategy

 (org.apache.shiro.authc.pam.AuthenticationStrategy)組件。配置驗證成功與失敗的條件。

Authorizer (org.apache.shiro.authz.Authorizer)

授權組件,指用戶訪問特定應用程式的機制。

SessionManager (org.apache.shiro.session.mgt.SessionManager)

管理會話如何創建生命周期。其中包括的sessiondao是管理會議數據的持久操作:SessionDAO (org.apache.shiro.session.mgt.eis.SessionDAO),代表執行sessionManager的CRUD操作。

CacheManager (org.apache.shiro.cache.CacheManager)

緩存管理模塊。

Cryptography (org.apache.shiro.crypto.*)

加密模塊。

Realms (org.apache.shiro.realm.Realm)

多種方式處理的橋梁。

 

多種配置方式:

與spring,jboss,guice等進行配置。

1,編程方式配置

例如:

view sourceprint?
Realm realm = //instantiate or acquire a Realm instance.  We'll discuss Realms later.
  
SecurityManager securityManager = new DefaultSecurityManager(realm);
//Make the SecurityManager instance available to the entire application via static memory:
SecurityUtils.setSecurityManager(securityManager);

2,sessionManager對象圖

如果你想使用sessionManager配置自定義的sessionDao信息,進行自定義會話管理

view sourceprint?
...
  
DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
SessionDAO sessionDAO = new CustomSessionDAO();
  
((DefaultSessionManager)securityManager.getSessionManager()).setSessionDAO(sessionDAO);
...

3,INI配置

1) 創建一個INI從SecurityManager

可以從多種方式讀取INI配置文件的信息,如文件系統,類路徑等

view sourceprint?
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.IniSecurityManagerFactory;
...
  
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);

2) 通過Ini實例讀取

類似於Properties的方式

view sourceprint?
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.Ini;
import org.apache.shiro.config.IniSecurityManagerFactory;
...
  
Ini ini = new Ini();
//populate the Ini instance as necessary
...
Factory<SecurityManager> factory = new IniSecurityManagerFactory(ini);
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);

載入之後就可以操作INI的配置了。

4,INI配置

每一個節點都是單獨的,不可以重覆,註釋可以使用#或者;

配置示例

view sourceprint?
# =======================
# Shiro INI configuration
# =======================
[main]
# Objects and their properties are defined here, 
# Such as the securityManager, Realms and anything
# else needed to build the SecurityManager
  
[users]
# The 'users' section is for simple deployments
# when you only need a small number of statically-defined 
# set of User accounts.
  
[roles]
# The 'roles' section is for simple deployments
# when you only need a small number of statically-defined
# roles.
  
[urls]
# The 'urls' section is used for url-based security
# in web applications.  We'll discuss this section in the
# Web documentation

1) [main]

配置sessionManager的實例和它的依賴。

配置示例

view sourceprint?
[main]
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
  
myRealm = com.company.security.shiro.DatabaseRealm
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
myRealm.password = secret
myRealm.credentialsMatcher = $sha256Matcher
securityManager.sessionManager.globalSessionTimeout = 1800000

定義一個對象

view sourceprint?
[main]
myRealm = com.company.shiro.realm.MyRealm
...

簡單的屬性設置

view sourceprint?
...
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
...

配置信息將轉入到對應的set方法中

view sourceprint?
...
myRealm.setConnectionTimeout(30000);
myRealm.setUsername("jsmith");
...

參考值

你可以使用$符號引用先前定義的一個對象的實例

view sourceprint?
...
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • String類的三個內建正則表達式工具: 1.matches()方法 示例:檢查一個句子是否以大寫字母開頭,以句號結尾 1 public static boolean checkFormat(String sentence){ 2 return sentence.matches("^[A-Z].+\
  • 本章主要是講解讀者在進行FPGA邏輯設計之前的準備工作,需要下載Quartus II軟體和 Modelsim 軟體,一個是用來進行FPGA邏輯設計,一個是用來對邏輯進行理論分析與驗證。 1.1 quartus 軟體安裝 現在Quartus II軟體已經更新到了15.0版本,這個最新版本的一些特性如下
  • 1. 用“==”比較兩個變數,如果兩個變數是基本類型變數,且都是數值類,則值相等就返回true 如果兩個變數是引用型變數,則兩個對象的地址一樣,即指向同一個對象,則返回true 2.equals:String類對equals進行了重寫:1)若是同一個對象,返回true; 2)若不是,則比較它們的值,
  • 平常閱讀源碼什麼的沒有目的性,所以很少去看什麼源碼,主要是比較繞看起來吃力,所以一般工作只是找個模版模仿一下。 以上廢話,割———————————————————————————————————————————————————————————— 最近照常模仿使用了其它項目里的DataSource用法
  • 一、自動化類型轉換:在某種條件下,系統自動完成類型轉換也稱為隱含轉換 ① 兩種類型相容 ② 目標類型大於源類型 ③ 對於表達式,如果一個操作數為double型,則整個表達式可提升為double型 ④ 示例:int i=10;double d=i; 1 public class DataDemo2 2
  • 本文翻譯自《effective modern C++》,由於水平有限,故無法保證翻譯完全正確,歡迎指出錯誤。謝謝! 古人曾說事情的真相會讓你覺得很自在,但是在適當的情況下,一個良好的謊言同樣能解放你。這個Item就是這樣一個謊言。但是,因為我們在和軟體打交道,所以讓我們避開“謊言”這個詞,換句話來說
  • 這是對前一個spring小例子的解析
  • App與伺服器的通信介面如何設計得好,需要考慮的地方挺多的,在此根據我的一些經驗做一些總結分享,旨在拋磚引玉。 安全機制的設計 現在,大部分App的介面都採用RESTful架構,RESTFul最重要的一個設計原則就是,客戶端與伺服器的交互在請求之間是無狀態的,也就是說,當涉及到用戶狀態時,每次請求都
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...