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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...