<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 41  文章 - 7  trackbacks - 0
    <2016年8月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    常用鏈接

    留言簿

    隨筆分類(lèi)

    隨筆檔案

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    原文:http://shiro.apache.org/reference.html
    Apache Shiro介紹
    Apache Shiro是什么?
    Apache Shiro 是一個(gè)可干凈處理認(rèn)證,授權(quán),企業(yè)會(huì)話管理以及加密的強(qiáng)大且靈活的開(kāi)源安全框架.
    Apache Shiro的首要目標(biāo)是易于使用和理解. 安全可以是非常復(fù)雜的,有時(shí)甚至是痛苦的,但它不是.
    框架應(yīng)該隱藏復(fù)雜的地方,暴露干凈而方便的API,以簡(jiǎn)化開(kāi)發(fā)者的努力進(jìn)而使其程序安全.
    下面是Apache Shiro可以做的事情:
    • 認(rèn)證用戶(hù)的身份
    • 實(shí)施用戶(hù)訪問(wèn)控制,如:
    • 確定用戶(hù)是否分配了某個(gè)角色
    • 確定用戶(hù)是否允許做某些事情
    • 任何環(huán)境中均可使用Session API, 即使是非web環(huán)境或EJB容器
    • 反映在認(rèn)證,訪問(wèn)控制,或會(huì)話生命期之間的事件.
    • 聚合一個(gè)或多個(gè)用戶(hù)安全數(shù)據(jù)數(shù)據(jù)源,以將其作為單一的組合用戶(hù)視圖.
    • 可開(kāi)啟Single Sign On (SSO) 功能
    • 為用戶(hù)無(wú)須再次登錄開(kāi)啟 'Remember Me'服務(wù)
    ...
    還有更多-所有都集成在緊密結(jié)合的易于使用的API中.
    Shiro試圖在所有應(yīng)用環(huán)境中都實(shí)現(xiàn)這些目標(biāo) - 從最簡(jiǎn)單的命令行應(yīng)用程序到大型企業(yè)應(yīng)用程序,它不強(qiáng)制依賴(lài)于第三方框架,容器,或應(yīng)用程序服務(wù)器.
    當(dāng)然,在可能的情況下,也可以將其整合到這些環(huán)境中, 但它在任何環(huán)境中都是開(kāi)箱即可使用的.
    Apache Shiro 特性
    Apache Shiro是一個(gè)包含多種特性的綜合應(yīng)用安全框架。下圖展示了Shiro的主要特性,本參考手冊(cè)也會(huì)參照下面的特性來(lái)組織內(nèi)容:

    Shiro的目標(biāo)(Shiro開(kāi)發(fā)團(tuán)隊(duì)稱(chēng)其為“四大應(yīng)用安全基石”)是認(rèn)證、授權(quán)、會(huì)話管理、加密:
    • 認(rèn)證: 有時(shí)稱(chēng)為登錄, 用于驗(yàn)證用戶(hù)身份. 
    • 授權(quán): 訪問(wèn)控制過(guò)程,如,確定誰(shuí)能訪問(wèn)什么. 
    • 會(huì)話管理: 管理特定用戶(hù)會(huì)話,即使是非web環(huán)境或EJB應(yīng)用程序 
    • 加密: 雖使用加密算法來(lái)保證數(shù)據(jù)安全, 但仍然易于使用.
    也有其它功能,以在不同的應(yīng)用環(huán)境中支持和加強(qiáng)這些特性,特別是:
    • Web 支持 — Shiro的web支持APIs可幫助你容易地保護(hù)web應(yīng)用程序安全.
      • 緩存 — 緩存是在Apache ShiroAPI的一等公民,在確保安全操作的同時(shí)能確保快速和有效。
      • 并發(fā)性- Apache Shiro的并發(fā)特性被設(shè)計(jì)為支持多線程的應(yīng)用。
      • 測(cè)試 —測(cè)試支持簡(jiǎn)化了單元和集成測(cè)試的創(chuàng)建,并確保您的代碼如預(yù)期一樣的安全。
      • "Run As" — Shiro 允許用戶(hù)以其它用戶(hù)的身份(如果有資格的話)來(lái)運(yùn)行, 這種特性在管理場(chǎng)景中非常有用.
      • "Remember Me" — Shiro 可以跨會(huì)話來(lái)記住用戶(hù)身份,這樣只在強(qiáng)制的情況下才需要用戶(hù)登錄.
    第一個(gè) Apache Shiro 應(yīng)用程序
    如果你從未接觸過(guò)Apache Shiro,這篇簡(jiǎn)短的指南會(huì)向你展示如何使用Apache Shiro來(lái)設(shè)置一個(gè)初始和非常簡(jiǎn)單的安全web應(yīng)用程序. 我們將討論Shiro的核心概念來(lái)幫助您熟悉Shiro的設(shè)計(jì)和API。
    如果你不想遵從本指南來(lái)編輯文件,你可以從下面的位置來(lái)選擇獲取幾乎相同的示例程序,并按照你的方式來(lái)引用:
    設(shè)置
    在這個(gè)簡(jiǎn)單的例子中, 我們會(huì)創(chuàng)建一個(gè)非常簡(jiǎn)單的快速運(yùn)行和退出的命令行應(yīng)用程序, 這只是為了讓你對(duì) Shiro的API有所感覺(jué).
    任何應(yīng)用程序
    Apache Shiro從最初就被設(shè)計(jì)用于支持任何應(yīng)用程序- 從最小的命令行程序到大型集群web應(yīng)用程序. 雖然在本指南中我們創(chuàng)建的是一個(gè)簡(jiǎn)單app,但不管應(yīng)用程序是如何創(chuàng)建或無(wú)論部署在什么地方,都可以應(yīng)用同樣的使用模式.
    本指南需要Java 1.5+.同時(shí)也會(huì)使用 Apache Maven 作為我們的構(gòu)建工具,當(dāng)然對(duì)于Apache Shiro的使用,這不是必須的.你可以獲取Shiro的jars,并以你喜歡的方式來(lái)進(jìn)行組合,例如可以使用 Apache AntIvy.
    對(duì)于本指南,請(qǐng)確保你使用的是Maven 2.2.1+. 你可以在命令中輸入mvn --version查看類(lèi)似于下面的東西:
    Testing Maven Installation
    hazlewood:~/shiro-tutorial$ mvn --version
    Apache Maven 2.2.1 (r801777; 2009-08-06 12:16:01-0700)
    Java version: 1.6.0_24
    Java home: /
    System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    Default locale: en_US,
    platform encoding: MacRoman
    OS name:
    "mac os x"
    version:
    "10.6.7"
    arch:
    "x86_64"
    Family:
    "mac"
    現(xiàn)在,在你的文件系統(tǒng)中創(chuàng)建一個(gè)新目錄,例如, shiro-tutorial ,并將下面的pom.xml 文件放在那個(gè)目錄中:
    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns=
    "http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.shiro.tutorials</groupId>
    <artifactId>shiro-tutorial</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>First Apache Shiro Application</name>
    <packaging>jar</packaging>
    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <configuration>
    <source>1.5</source> <target>1.5</target>
    <encoding>${project.build.sourceEncoding}</encoding>
    </configuration> </plugin>
    <!-- This plugin is only to test run our little application. It is not needed in most Shiro-enabled applications: -->
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.1</version>
    <executions>
    <execution>
    <goals>
    <goal>java</goal>
    </goals>
    </execution>
    </executions>
    <configuration>
    <classpathScope>test</classpathScope>
    <mainClass>Tutorial</mainClass>
    </configuration>
    </plugin>
    </plugins>
    </build>
    <dependencies>
    <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.1.0</version>

    </dependency>
    <!-- Shiro uses SLF4J for logging. We'll use the 'simple' binding in this example app. See http://www.slf4j.org for more info. -->
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.6.1</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
    </project>
    Tutorial 類(lèi)
    我們將運(yùn)行一個(gè)簡(jiǎn)單的命令行應(yīng)用程序,因此我們需要?jiǎng)?chuàng)建一個(gè)帶有public static void main(String[] args)方法的java類(lèi).
    在包含pom.xml文件的同一個(gè)目錄中,創(chuàng)建一個(gè)src/main/java子目錄,并使用下面的內(nèi)容在其中創(chuàng)建一個(gè)Tutorial.java文件:
    src/main/java/Tutorial.java
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    public class Tutorial {
    private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);
    public static void main(String[] args) {
    log.info(
    "My First Apache Shiro Application");
    System.exit(0);
    }
    }
    現(xiàn)在不用擔(dān)心import語(yǔ)句- 我們很快就會(huì)講解它們. 現(xiàn)在,我們已經(jīng)有了一個(gè)典型的命令行程序外殼. 程序會(huì)打印文件"My First Apache Shiro Application"并退出.
    測(cè)試運(yùn)行
    要測(cè)試我們的Tutorial應(yīng)用程序,切換到tutorial根目錄(即.shiro-tutorial),在命令行提示窗口中執(zhí)行下面的命令:
    mvn compile exec:java
    然后你將看到我們的Tutorial 程序運(yùn)行和退出.你可能會(huì)看到與下面相似的內(nèi)容(注意,粗文本表示我們的輸出):
    運(yùn)行程序
    lhazlewood:~/projects/shiro-tutorial$ mvn compile exec:java
    ... a bunch of Maven output ...
    1 [Tutorial.main()] INFO Tutorial - My First Apache Shiro Application
    lhazlewood:~/projects/shiro-tutorial\$
    到此我們已經(jīng)驗(yàn)證了應(yīng)用程序能成功運(yùn)行 -現(xiàn)在讓我們啟用Apache Shiro. 在繼續(xù)本指南的過(guò)程中,每次修改代碼后,你都可以運(yùn)行mvn compile exec:java 來(lái)查看結(jié)果變化.
    啟用Shiro
    理解啟用Shiro的第一件事是幾乎Shiro中的每件事情都與核心組件SecurityManager有關(guān). 對(duì)于那些熟悉Java安全的人來(lái)說(shuō),這是Shiro的SecurityManager概念 -它不同于java.lang.SecurityManager.
    Architecture 章節(jié)中,我們會(huì)詳細(xì)講解Shiro的設(shè)計(jì),對(duì)于現(xiàn)在來(lái)說(shuō),只需要知道Shiro SecurityManager 是Shiro 環(huán)境中的核心且每個(gè)程序都必須存在一個(gè)SecurityManager 就足夠了.
    因此,在Tutorial 程序中,我們要做的第一件事就是建立SecurityManager實(shí)例.
    配置
    雖然我們可以直接實(shí)例化SecurityManager類(lèi), Shiro的SecurityManager 實(shí)現(xiàn)包含足夠的配置選項(xiàng)和內(nèi)部組件,使其可以從Java源代碼中進(jìn)行構(gòu)建- 但可以使用靈活的文本配置格式來(lái)更簡(jiǎn)單地配置SecurityManager.
    為此, Shiro通過(guò)基于文本的 INI 配置提供了一個(gè)缺省的公共解決方案 . 現(xiàn)在,人們都厭倦了使用笨重的XML文件,INI易于閱讀,簡(jiǎn)單易用,并且需要極少依賴(lài)。稍后你也會(huì)看到,用一個(gè)簡(jiǎn)單的對(duì)象圖導(dǎo)航,INI可像SecurityManager一樣有效地配置簡(jiǎn)單的對(duì)象圖.
    多個(gè)配置選項(xiàng)
    Shiro的 SecurityManager實(shí)現(xiàn)以及所有支持組件都是JavaBeans 兼容的. 這允許Shiro使用特定的配置格式來(lái)進(jìn)行配置,配置格式如 XML (Spring, JBoss, Guice, etc), YAML, JSON, Groovy Builder 標(biāo)記等等.
    INI只是Shiro的共同解決方案,它允許在任何環(huán)境中進(jìn)行配置.
    shiro.ini
    對(duì)于這個(gè)簡(jiǎn)單應(yīng)用程序,因此我們使用INI文件來(lái)配置Shiro SecurityManager.首先,在與pom.xml相同的目錄中,創(chuàng)建一個(gè) src/main/resources 目錄. 然后使用下面的命令,在新創(chuàng)建的目錄中創(chuàng)建一個(gè)shiro.ini文件:

    src/main/resources/shiro.ini
    # =============================================================================
    # Tutorial INI configuration
    #
    # Usernames/passwords are based on the classic Mel Brooks' film
    "Spaceballs" :)
    # =============================================================================
    # -----------------------------------------------------------------------------
    # Users and their (optional) assigned roles # username = password, role1, role2, ..., roleN
    # -----------------------------------------------------------------------------
    [users] root = secret, admin
    guest = guest, guest
    presidentskroob = 12345, president
    darkhelmet = ludicrousspeed, darklord, schwartz
    lonestarr = vespa, goodguy, schwartz
    # -----------------------------------------------------------------------------
    # Roles with assigned permissions
    # roleName = perm1, perm2, ..., permN
    # -----------------------------------------------------------------------------
    [roles]
    admin = *
    schwartz = lightsaber:*
    goodguy = winnebago:drive:eagle5
    正如你看到的,這個(gè)配置基本建立一套小的靜態(tài)用戶(hù)帳戶(hù),對(duì)于我們的第一個(gè)程序來(lái)說(shuō),已經(jīng)足夠了.在后面的章節(jié)中,你會(huì)看到如何使用更復(fù)雜的用戶(hù)數(shù)據(jù)資源,如關(guān)系數(shù)據(jù)庫(kù),LDAP的ActiveDirectory等等.
    引用配置
    現(xiàn)在我們已經(jīng)定義了一個(gè)INI文件, 然后我們就可在Tutorial類(lèi)中創(chuàng)建SecurityManager實(shí)例了. 修改main方法,以反映下面的更新:
    public static void main(String[] args) {
    log.info(
    "My First Apache Shiro Application");
    //1.
    Factory<
    SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    //2.
    SecurityManager securityManager = factory.getInstance();
    //3.
    SecurityUtils.setSecurityManager(securityManager);
    System.exit(0);
    }
    在添加了3行代碼后,我們就在樣例程序中啟用了Shiro!是不是很簡(jiǎn)單?
    運(yùn)行 mvn compile exec:java能看到一切都能成功運(yùn)行(因?yàn)镾hiro默認(rèn)為debug或更低級(jí)別,你不會(huì)看到任何Shiro日志消息-如果啟動(dòng)或運(yùn)行時(shí)不出現(xiàn)錯(cuò)誤,那么一切就工作得很好).
    以下是上面增加代碼所做的事情:
    1. 我們使用Shiro的IniSecurityManagerFactory實(shí)現(xiàn)來(lái)獲取位于classpath根下的shiro.ini文件.此實(shí)現(xiàn)了反映了Shiro對(duì)工廠設(shè)計(jì)模式的支持. classpath: 前輟是一個(gè)資源標(biāo)識(shí)符,用于告訴shiro在什么位置加載ini文件(也支持其它前輟,像url: 和file: ). 
    1. 然后調(diào)用了factory.getInstance()方法,它會(huì)解析INI文件,并返回一個(gè)反映配置的SecurityManager實(shí)例. 
    1. 在這個(gè)簡(jiǎn)單示例中,我們將SecurityManager設(shè)為了一個(gè)可通過(guò)JVM來(lái)訪問(wèn)的static (memory) 單例.請(qǐng)注意,如果在單個(gè)虛擬機(jī)中存在多個(gè)啟用了Shiro的應(yīng)用程序,這是不理想的.對(duì)于這個(gè)簡(jiǎn)單示例,它是OK的, 但在更復(fù)雜的應(yīng)用程序環(huán)境中,通常應(yīng)該將SecurityManager放置在特定應(yīng)用的內(nèi)存中(如,放在web app的ServletContext中或Spring, Guice或 JBoss DI 容器實(shí)例中).
    使用Shiro
    現(xiàn)在我們建立好了SecurityManager,可以準(zhǔn)備使用了, 現(xiàn)在讓我們做一些我們真正關(guān)心的東西 - 執(zhí)行安全操作.
    當(dāng)為我們的應(yīng)用程序提供安全時(shí),我們通常問(wèn)自己最相關(guān)的問(wèn)題是"當(dāng)前用戶(hù)是誰(shuí)?”或“是否允許當(dāng)前用戶(hù)做某些事情”? 這是經(jīng)常會(huì)問(wèn)的問(wèn)題,因此我們會(huì)編寫(xiě)代碼并設(shè)計(jì)我們的接口:
    應(yīng)用程序通常會(huì)基于用戶(hù)存儲(chǔ)進(jìn)行構(gòu)建, 并且你希望每個(gè)用戶(hù)都是安全的. 因此,對(duì)于我們來(lái)說(shuō),最自然的方式是認(rèn)為應(yīng)用程序的安全是基于當(dāng)前用戶(hù)的. Shiro的 API從根本上使用了Subject概念來(lái)表達(dá)當(dāng)前用戶(hù).
    在幾乎所有環(huán)境中,你可以通過(guò)下面的調(diào)用來(lái)獲取當(dāng)前執(zhí)行用戶(hù):
    Subject currentUser = SecurityUtils.getSubject();
    使用SecurityUtils.getSubject(), 我們能獲取當(dāng)前執(zhí)行的SubjectSubject是一種安全術(shù)語(yǔ),其基本意義為"當(dāng)前執(zhí)行用戶(hù)的特定安全視圖". 它不稱(chēng)為'User',因?yàn)?'User' 這個(gè)詞通常與人類(lèi)聯(lián)系在一起.
    在安全世界中,術(shù)語(yǔ)'Subject'可以表示人類(lèi),但也可以表示第三過(guò)程, cron job, 后臺(tái)帳戶(hù),或任何相似的東西.它簡(jiǎn)單地表示為當(dāng)前與軟件交互的事物.
    雖然這只是針對(duì)大多數(shù)的意圖和目的,你仍然可將Subject認(rèn)為是Shiro的'User'.
    在一個(gè)獨(dú)立的應(yīng)用程序中,getSubject()方法會(huì)返回在應(yīng)用特定位置用戶(hù)數(shù)據(jù)的基礎(chǔ)上返回一個(gè)Subject,在服務(wù)器環(huán)境中(如. web app),它會(huì)基于當(dāng)前線程或傳入請(qǐng)求相關(guān)的用戶(hù)數(shù)據(jù)中來(lái)獲取Subject.
    現(xiàn)在你有了Subject,你能用它來(lái)做什么呢?
    如果你想在應(yīng)用程序其會(huì)話期間對(duì)當(dāng)前用戶(hù)做些什么,你可以獲取它們的會(huì)話:
    Session session = currentUser.getSession(); session.setAttribute( "someKey", "aValue" );
    Session是Shiro特有的實(shí)例,它提供了類(lèi)似常規(guī)HttpSessions大部分的功能,但也存在額外的東西以及一個(gè)重大區(qū)別:它不需要HTTP環(huán)境!
    如果部署在web應(yīng)用程序中,默認(rèn)情況下,Session是基于HttpSession的. 但在非web環(huán)境中,就像這個(gè)簡(jiǎn)單的tutorial程序, Shiro會(huì)默認(rèn)自動(dòng)使用其企業(yè)級(jí)會(huì)話管理.
    這意味著,無(wú)論是哪種部署環(huán)境,無(wú)論在哪一層,在你的應(yīng)用程序中都可以使用同一套API. 這打開(kāi)了應(yīng)用程序的新世界,因?yàn)槿魏螒?yīng)用程序都可以不強(qiáng)制使用 HttpSession或EJB有狀態(tài)會(huì)話bean的前提下獲取Session. 除此之外,任何client技術(shù)現(xiàn)在都可以共享會(huì)話數(shù)據(jù).
    所以現(xiàn)在你可以獲取Subject及其會(huì)話了.像檢查它們是否允許做某些事情以及檢查其角色與權(quán)限這樣真正有用的事情又怎樣呢?
    我們只能為一個(gè)已知的用戶(hù)做這些檢查。上面的Subject實(shí)例只能代表當(dāng)前用戶(hù),但當(dāng)前用戶(hù)是誰(shuí)呢? 這里,它們是匿名的- 也就是說(shuō),除非它們至少登錄了一次,才知道是已知的. 因此, 讓我們按下面這樣做:
    if ( !currentUser.isAuthenticated() ) {
    //collect user principals and credentials in a gui specific manner
    //such as username/password html form, X509 certificate, OpenID, etc.
    //We'll use the username/password example here since it is the most common.
    UsernamePasswordToken token =
    new UsernamePasswordToken("lonestarr", "vespa");
    //this is all you have to do to support 'remember me' (no config - built in!):
    token.setRememberMe(
    true);
    currentUser.login(token);
    }
    這就是它了!不能再容易了.
    但如果登錄失敗了呢? 你可以捕獲各種各樣的異常,這些異常將明確地告訴你發(fā)生了什么,并允許你進(jìn)行相應(yīng)地處理:
    try {
    currentUser.login( token );
    //if no exception, that's it, we're done!
    } catch ( UnknownAccountException uae ) {
    //username wasn't in the system, show them an error message?
    } catch ( IncorrectCredentialsException ice ) {
    //password didn't match, try again? }
    catch ( LockedAccountException lae ) {
    //account for that username is locked - can't login. Show them a message?
    }
    ... more types exceptions to check
    if you want ...
    }
    catch ( AuthenticationException ae ) {
    //unexpected condition - error?
    }
    你可以捕獲多種不同類(lèi)型的異常,或者拋出Shiro未出現(xiàn)的自定義異常.參考AuthenticationException JavaDoc 來(lái)了解更多.
    溫馨提示
    最佳安全實(shí)踐是向用戶(hù)提示一般的登錄失敗消息,因?yàn)槟悴幌霂椭粽咴噲D闖入你的系統(tǒng).
    Ok, 到現(xiàn)在為止,我們有了一個(gè)登錄用戶(hù).還有什么事情可以做呢?
    讓我們看看它是誰(shuí):
    //print their identifying principal (in this case, a username):
    log.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
    我們也可以測(cè)試它是否有指定的角色:
    if ( currentUser.hasRole( "schwartz" ) ) {
    log.info(
    "May the Schwartz be with you!" );
    }
    else {
    log.info(
    "Hello, mere mortal." );
    }
    我們還可以測(cè)試它是否有某種類(lèi)型實(shí)體上的權(quán)限:
    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.");
    }
    此外,我們可以執(zhí)行一個(gè)非常強(qiáng)大的實(shí)例級(jí)權(quán)限檢查 - 查看用戶(hù)是否有能力訪問(wèn)一個(gè)特定類(lèi)型的實(shí)例:
    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!");
    }
    非常簡(jiǎn)單,對(duì)嗎?
    最后,當(dāng)用戶(hù)在程序程序中完成了使用,它們可以登出:
    currentUser.logout(); //removes all identifying information and invalidates their session too.
    最終Tutorial類(lèi)
    在添加了上述代碼后,以下是最終的Tutorial類(lèi)文件.只要你喜歡,你可以隨意編輯,并修改安全檢查(和INI配置)來(lái)玩它:
    Final src/main/java/Tutorial.java
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    public class Tutorial {
    private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);
    public static void main(String[] args) {
    log.info(
    "My First Apache Shiro Application");
    Factory<
    SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);
    // get the currently executing user:
    Subject currentUser = 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 + "]");
    }
    // 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();
    System.exit(0);
    }
    }
    總結(jié)
    希望這本入門(mén)教程幫助你了解如何在一個(gè)基本應(yīng)用中設(shè)置Shiro,以及Shiro的主要設(shè)計(jì)理念 Subject 和SecurityManager。
    但這是一個(gè)相當(dāng)簡(jiǎn)單的應(yīng)用。你可能會(huì)問(wèn)自己,“如果我不想使用INI用戶(hù)帳戶(hù)而是要連接到一個(gè)更復(fù)雜的用戶(hù)數(shù)據(jù)源,又該怎么做呢?”
    要回答這個(gè)問(wèn)題,需要深入一點(diǎn)了解Shiro的架構(gòu)和支持的配置機(jī)制。我們將下一個(gè)Shiro的Architecture 進(jìn)行講解.
    Apache Shiro 架構(gòu)
    Apache Shiro的設(shè)計(jì)目標(biāo)是通過(guò)直觀而簡(jiǎn)單的方式來(lái)簡(jiǎn)化應(yīng)用程序安全的開(kāi)發(fā). Shiro的核心設(shè)計(jì)模型-在一個(gè)上下文里與應(yīng)用程序進(jìn)行交互.
    軟件應(yīng)用程序程序通常是基于用戶(hù)存儲(chǔ)來(lái)設(shè)計(jì)的. 也就是說(shuō),你會(huì)經(jīng)常設(shè)計(jì)用戶(hù)如何與軟件進(jìn)行交互的接口或服務(wù).
    例如,你可能會(huì)說(shuō), "如果用戶(hù)與應(yīng)用程序交互時(shí)已經(jīng)登錄了,我應(yīng)該向其展示一個(gè)按鈕,它們可以點(diǎn)擊來(lái)查看它們的帳戶(hù)信息.如果它們沒(méi)有登錄,我將向它們展示一個(gè)登錄按鈕."
    此示例語(yǔ)句暗示了應(yīng)用程序在很大程度上是為了滿(mǎn)足用戶(hù)的需求而編寫(xiě)的。即使'用戶(hù)'是另一個(gè)軟件系統(tǒng),而不是一個(gè)人,你仍然要編寫(xiě)代碼來(lái)反映誰(shuí)(或什么)目前正在與您的軟件交互。
    高層次概述
    在最高概念層面,Shiro的架構(gòu)包含了3個(gè)主要概念:Subject, SecurityManager 和 Realms. 下面的圖表是這些組件如何交互的高級(jí)概述,我們將覆蓋下面的每一個(gè)概念:



    Subject:
    正如我們?cè)?nbsp;Tutorial中提到的, Subject本質(zhì)上當(dāng)前執(zhí)行用戶(hù)的特定安全視圖.
    "User”往往意味著一個(gè)人類(lèi),一個(gè)Subject可以是一個(gè)人,但它也可能代表一個(gè)第三方服務(wù),后臺(tái)賬戶(hù),cron作業(yè),或任何類(lèi)似的東西-基本上是當(dāng)前與軟件交互的任何東西. 
    Subject 實(shí)例都綁定在SecurityManager上. 當(dāng)你與Subject交互時(shí),這些交互都會(huì)轉(zhuǎn)換成特定subject與SecurityManager的交互. 
    SecurityManager:
    SecurityManager 是Shiro架構(gòu)的心臟,它扮演了一種保護(hù)傘(umbrella)對(duì)象,協(xié)調(diào)其內(nèi)部的安全組件共同形成一個(gè)對(duì)象圖.
    然而,一旦應(yīng)用程序配置了SecurityManager及其內(nèi)部對(duì)象圖,它就會(huì)退居幕后,應(yīng)用開(kāi)發(fā)人員幾乎把他們的所有時(shí)間都花在Subject API調(diào)用上。
    后面我們會(huì)詳細(xì)討論SecurityManager, 但要意識(shí)到,當(dāng)你與Subject交互時(shí),其實(shí)是幕后的SecurityManager在執(zhí)行Subject的安全操作.這可以從上面的圖中得到反映.
    Realms:
    Realms扮演的是Shiro與應(yīng)用程序安全數(shù)據(jù)的橋梁或連接器.
    當(dāng)它與像用戶(hù)帳戶(hù)這樣的相關(guān)安全數(shù)據(jù)進(jìn)行實(shí)際交互時(shí),如執(zhí)行認(rèn)證(login) 和授權(quán)(訪問(wèn)控制), Shiro會(huì)查看為應(yīng)用程序中配置的一個(gè)或多個(gè)Realms. 
    從這種意義上說(shuō),Realm本質(zhì)上是一個(gè)帶有安全特征的數(shù)據(jù)訪問(wèn)對(duì)象(DAO): 它封裝了數(shù)據(jù)源的連接細(xì)節(jié),并按需將相關(guān)數(shù)據(jù)提供給Shiro.
    當(dāng)配置Shiro時(shí),你必須至少指定一個(gè)Realm來(lái)用于驗(yàn)證或授權(quán). SecurityManager可配置多個(gè)Realms, 但至少要配置一個(gè). 
    Shiro提供了多個(gè)開(kāi)箱即用的Realms來(lái)連接多種安全數(shù)據(jù)源,如LDAP, 關(guān)系型數(shù)據(jù)庫(kù)(JDBC),像INI和屬性文件這樣的文本配置源.
    如果默認(rèn)的Realms不能滿(mǎn)足你的需要,你可以插入你自己的Realm實(shí)現(xiàn)來(lái)表示自定義數(shù)據(jù)源. 
    像其它內(nèi)部組件一樣, Shiro SecurityManager會(huì)對(duì)如何使用Realms來(lái)獲取安全身份數(shù)據(jù)(表示為Subject實(shí)例)進(jìn)行管理.
    詳細(xì)架構(gòu)
    下圖展示了Shiro的核心架構(gòu)概念以及每種概念的簡(jiǎn)短概述:

    與軟件進(jìn)行交互的實(shí)體(用戶(hù),第三方服務(wù),cron作業(yè)等等)特定安全視圖. 
    正如上面提到的, SecurityManager是Shiro架構(gòu)的心臟.它主要充當(dāng)保護(hù)傘對(duì)象,協(xié)調(diào)其管理組件來(lái)確保工作順利進(jìn)行. 同時(shí),它也會(huì)管理每個(gè)應(yīng)用程序用戶(hù)的Shiro視圖,因此它知道如何執(zhí)行每個(gè)用戶(hù)上的操作.
    認(rèn)證負(fù)責(zé)驗(yàn)證用戶(hù)的登錄. 當(dāng)一個(gè)用戶(hù)試圖登錄時(shí),認(rèn)證將執(zhí)行驗(yàn)證邏輯. 認(rèn)證組件知道如何協(xié)調(diào)一個(gè)或多個(gè)存儲(chǔ)相關(guān)用戶(hù)信息的. 從Realms中獲取的數(shù)據(jù)用于驗(yàn)證用戶(hù)的身份,以確保其合法性.
    如果配置了多個(gè)Realm, AuthenticationStrategy 會(huì)協(xié)調(diào)Realms來(lái)確定在哪些情況下認(rèn)證是成功或是失敗的(例如,如果某個(gè)realm是成功的,但其它是失敗的l,那么認(rèn)證是成功的嗎?
    是否需要所有realms都成功?還是只需要第一個(gè)成功?). 
    授權(quán)是在應(yīng)用程序中負(fù)責(zé)確定訪問(wèn)控制的組件.最終說(shuō)來(lái)它只是允許用戶(hù)做什么或不做什么的機(jī)制.類(lèi)似于Authenticator,Authorizer也知道如何協(xié)調(diào)多個(gè)后端數(shù)據(jù)源來(lái)訪問(wèn)角色和權(quán)限信息.
    Authorizer可使用這些信息來(lái)決定一個(gè)用戶(hù)是否允許來(lái)執(zhí)行給定的操作. 
    SessionManager知道如何來(lái)創(chuàng)建和管理用戶(hù)生命周期,以為所有環(huán)境中的用戶(hù)提供強(qiáng)大的會(huì)話體驗(yàn). 在安全框架的世界中,這是獨(dú)特的特性- Shiro有管理任何環(huán)境中用戶(hù)會(huì)話的能力, 即使這些環(huán)境處于非Web/Servlet或在EJB容器環(huán)境.
    默認(rèn)情況下,如果可行的話,Shiro會(huì)使用現(xiàn)有的會(huì)話機(jī)制, (例如. Servlet容器),但如果不存在這樣的環(huán)境,如獨(dú)立程序或非web環(huán)境,它會(huì)使用內(nèi)置的企業(yè)會(huì)話管理來(lái)提供相同的編程體驗(yàn). SessionDAO的存在允許使用任何數(shù)據(jù)源來(lái)存儲(chǔ)會(huì)話. 
    SessionDAO可代表SessionManager來(lái)執(zhí)行會(huì)話持久化操作(CRUD).這允許在會(huì)話管理框架中插入任何數(shù)據(jù)存儲(chǔ). 
    緩存管理器用于創(chuàng)建和管理其它Shiro組件使用的緩存實(shí)例生命周期.因?yàn)镾hiro在執(zhí)行認(rèn)證,授權(quán)和會(huì)話管理時(shí),可訪問(wèn)多個(gè)后端數(shù)據(jù)源,當(dāng)使用這些數(shù)據(jù)源時(shí),緩存通常是框架中提高性能的最好架構(gòu)特征.
    任何一個(gè)現(xiàn)代開(kāi)源或企業(yè)級(jí)緩存產(chǎn)品都可以插入到Shiro中,以提供快速,高效的用戶(hù)體驗(yàn). 
    加密是企業(yè)級(jí)安全框架中一個(gè)很自然的功能. Shiro的加密包包含了易于使用和理解的加密 Ciphers, Hashes (aka digests)表現(xiàn)以及不同的編碼實(shí)現(xiàn).
    包中的所有類(lèi)都是精心設(shè)計(jì)為易于使用和理解. 任何使用過(guò)Java本地加密的人,都可以輕易地駕馭它.
    Shiro的加密APIs簡(jiǎn)化了復(fù)雜的Java機(jī)制,使得加密對(duì)于普通人來(lái)說(shuō)也能簡(jiǎn)單使用. 
    正如上面所提到的, Realms扮演的是Shiro與應(yīng)用程序安全數(shù)據(jù)之間的橋梁或連接器.
    當(dāng)它與像用戶(hù)帳戶(hù)這樣的相關(guān)安全數(shù)據(jù)進(jìn)行實(shí)際交互時(shí),如執(zhí)行認(rèn)證(login) 和授權(quán)(訪問(wèn)控制), Shiro會(huì)查看為應(yīng)用程序中配置的一個(gè)或多個(gè)Realms.
    你可以根據(jù)需要來(lái)配置多個(gè)Realms  (通常情況下一個(gè)數(shù)據(jù)源一個(gè)Realms) ,Shiro會(huì)按照需要來(lái)為認(rèn)證和授權(quán)協(xié)調(diào)數(shù)據(jù).
    SecurityManager
    因?yàn)镾hiro的API鼓勵(lì)使用以Subject為中心的編程模型,大部分應(yīng)用程序開(kāi)發(fā)者會(huì)極少直接與SecurityManager交互(框架開(kāi)發(fā)者有時(shí)可能會(huì)發(fā)現(xiàn)它很有用).
    即使是這樣,了解SecurityManager的功能,特別是在為應(yīng)用配置時(shí), 也是極其重要的.
    設(shè)計(jì)
    如前所述,應(yīng)用程序安全管理器會(huì)為所有應(yīng)用程序用戶(hù)執(zhí)行安全操作和管理用戶(hù)狀態(tài). 在Shiro的默認(rèn)SecurityManager實(shí)現(xiàn)中包含:
    • Authentication(認(rèn)證)
    • Authorization(授權(quán))
    • Session Management(會(huì)話管理)
    • Cache Management(緩存管理)
    • Realm coordination(Realm協(xié)作)
    • Event propagation(事件傳播)
    • "Remember Me" Services(記住我服務(wù))
    • Subject creation(Subject創(chuàng)建)
    • Logout(登出)
    等等.
    但在單個(gè)組件中,管理著多個(gè)功能. 而且,如果一切功能都集中到單一的實(shí)現(xiàn)類(lèi)中,會(huì)使這些操作變得靈活和可定制化是相當(dāng)困難的.
    為了簡(jiǎn)化配置和開(kāi)啟靈活的配置性/可插拔性, Shiro的實(shí)現(xiàn)設(shè)計(jì)上是高度模塊化的- SecurityManager實(shí)現(xiàn)及其類(lèi)層次并沒(méi)有做這么多工作.
    相反,SecurityManager實(shí)現(xiàn)幾乎充當(dāng)?shù)氖禽p量級(jí)容器組件, 幾乎把所有行為/操作都委派給了內(nèi)嵌/包裝組件.上面的詳細(xì)框架圖就反映了這種包裝設(shè)計(jì).
    雖然是由組件來(lái)實(shí)際執(zhí)行邏輯,SecurityManager實(shí)現(xiàn)知道如何以及何時(shí)來(lái)協(xié)調(diào)組件來(lái)完成正確行為.
    SecurityManager 實(shí)現(xiàn)同時(shí)也是JavaBeans兼容的,這允許你通過(guò)標(biāo)準(zhǔn)的Java訪問(wèn)器/修改器方法(get*/set*)來(lái)輕松地定制可插拔組件.
    這意味著Shiro的架構(gòu)模塊可以很容易配置自定義行為。
    簡(jiǎn)單配置
    由于JavaBeans的兼容性, 使其很容易地通過(guò)支持JavaBeans的自定義組件來(lái)配置SecurityManager,如Spring, Guice, JBoss等等.
    下面我們就會(huì)涵蓋 Configuration .
    Apache Shiro 配置
    Shiro設(shè)計(jì)為可工作于任何環(huán)境, 從簡(jiǎn)單的命令行應(yīng)用程序到大型企業(yè)集群應(yīng)用程序. 由于環(huán)境的多樣性,存在著多種配置機(jī)制. 本章講述Shiro核心支持的配置機(jī)制.
    多個(gè)配置選項(xiàng)
    Shiro的SecurityManager實(shí)現(xiàn)以及所有支持組件都是與JavaBeans兼容的.這允許Shiro使用特定配置格式,如常規(guī)Java, XML (Spring, JBoss, Guice, etc), YAML, JSON, Groovy Builder標(biāo)記來(lái)配置.
    編程配置
    創(chuàng)建SecurityManager并使用可用的最簡(jiǎn)單方式是創(chuàng)建一個(gè)org.apache.shiro.mgt.DefaultSecurityManager. 例如:
    Realm realm = //實(shí)例化或獲取一個(gè)Realm實(shí)例.我們后面會(huì)討論Realms. SecurityManager securityManager = new DefaultSecurityManager(realm); //通過(guò)靜態(tài)內(nèi)存,使SecurityManager 實(shí)例對(duì)整個(gè)應(yīng)用程序可用: SecurityUtils.setSecurityManager(securityManager);
    令人驚訝的是,雖只有3行代碼,但你現(xiàn)在有了一個(gè)適合于許多應(yīng)用且功能齊全的Shiro環(huán)境。多么容易!
    SecurityManager 對(duì)象圖
    正如在Architecture章節(jié)中討論的, Shiro的SecurityManager實(shí)現(xiàn)本質(zhì)上內(nèi)嵌特定安全的組件模塊對(duì)象圖.
    因?yàn)樗鼈円彩荍avaBeans兼容的,你可調(diào)用任何內(nèi)嵌組件上的 getter和setter方法來(lái)配置SecurityManager和它的內(nèi)部對(duì)象圖.
    例如,如果你想配置SecurityManager實(shí)例來(lái)使用自定義的SessionDAO來(lái)定制 Session Management,你可以直接使用內(nèi)置的SessionManager的setSessionDAO來(lái)設(shè)置SessionDAO:
    ...
    DefaultSecurityManager securityManager =
    new DefaultSecurityManager(realm);
    SessionDAO sessionDAO =
    new CustomSessionDAO();
    ((DefaultSessionManager)securityManager.getSessionManager()).setSessionDAO(sessionDAO);
    ...
    使用直接方法調(diào)用,你可以配置SecurityManager的對(duì)象圖的任何部分.
    雖像程序化定制一樣簡(jiǎn)單,但它并不代表大多數(shù)現(xiàn)實(shí)世界應(yīng)用程序的理想配置。
    有以下幾個(gè)原因?yàn)槭裁淳幊膛渲每赡懿贿m合您的應(yīng)用程序:
    • 它需要你了解和實(shí)例化一個(gè)直接實(shí)現(xiàn).如果不需要了解具體和查找位置,這是很好的. 
    • 由于Java的類(lèi)型安全特性,你需要在get*方法中對(duì)特定實(shí)現(xiàn)進(jìn)行類(lèi)型轉(zhuǎn)換. 因此太多的轉(zhuǎn)換是丑陋的,冗長(zhǎng)的,并緊密耦合了你的實(shí)現(xiàn)類(lèi).
    • SecurityUtils.setSecurityManager 方法調(diào)用使得實(shí)例化了的SecurityManager實(shí)例化了一個(gè) VM 靜態(tài)單例, 在這里是很好的,但對(duì)于多數(shù)應(yīng)用程序來(lái)說(shuō),如果在同一個(gè)JVM中運(yùn)行了多個(gè)開(kāi)啟了Shiro的應(yīng)用程序,將會(huì)引發(fā)問(wèn)題.本身來(lái)說(shuō),如果實(shí)例是應(yīng)用程序級(jí)單例的,這會(huì)更好,但不是靜態(tài)內(nèi)存引用. 
    • 為了讓Shiro配置生效,每次你都需要重新編譯代碼.
    但,即使有這些警告,直接編程操作方案對(duì)于內(nèi)存受限的環(huán)境,仍然是價(jià)值的,像智能手機(jī)應(yīng)用程序.如果你的應(yīng)用程序不會(huì)運(yùn)行內(nèi)存受限環(huán)境中,你會(huì)發(fā)現(xiàn)基于文本的配置更加簡(jiǎn)單和閱讀.
    INI 配置
    大部分應(yīng)用程序都受益于基于文本的配置,這樣可以獨(dú)立于源碼進(jìn)行修改,甚至使得那于不熟悉Shiro API的人來(lái)說(shuō),也更易于理解.
    為了確保通用基于文本配置的解決方案能工作于任何環(huán)境(有很小的依賴(lài)),Shiro支持使用 INI format 來(lái)構(gòu)建SecurityManager 對(duì)象圖和它的支撐組件.
    INI易于閱讀和配置,并可以簡(jiǎn)單建立而適用于大部分應(yīng)用程序.
    從INI創(chuàng)建SecurityManager
    下面有兩個(gè)例子來(lái)講述如何基于INI配置來(lái)構(gòu)建SecurityManager.
    從INI資源來(lái)構(gòu)建SecurityManager
    我們可以從INI資源路徑來(lái)創(chuàng)建SecurityManager實(shí)例. 資源可通過(guò)文件系統(tǒng), classpath,或URLs來(lái)獲取,此時(shí)其前輟分別為file:, classpath:, 或 url: .
    這個(gè)例子使用Factory來(lái)從classpath根路徑下來(lái)攝取shiro.ini文件,并返回SecurityManager實(shí)例:

    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);
    從INI實(shí)例來(lái)構(gòu)建SecurityManager
    INI配置也通過(guò)編程方式來(lái)構(gòu)建,即通過(guò)org.apache.shiro.config.Ini 類(lèi). Ini 類(lèi)的功能類(lèi)似于 JDK java.util.Properties 類(lèi),但還額外支持分段名稱(chēng)的分割.
    For example:
    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(); //按需填充 Ini實(shí)例
    ...
    Factory<
    SecurityManager> factory = new IniSecurityManagerFactory(ini);
    SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);
    現(xiàn)在,我們知道如何從INI配置來(lái)構(gòu)建一個(gè)SecurityManager, 讓我們明確地了解如何定義一個(gè)Shiro INI配置.
    INI 分段
    INI是一個(gè)包含由唯一分段組織的key/value對(duì)的文本配置. 每個(gè)段中Keys是唯一的,而不是整個(gè)配置(這一點(diǎn)不像JDK Properties).
    每個(gè)段都可像單個(gè)Properties定義進(jìn)行查看.
    注釋行可以#或;開(kāi)頭
    下面是分段的例子:
    # ======================= # Shiro INI configuration # =======================
    [main]
    # 這里用于定義對(duì)象及其屬性,如securityManager, Realms 以及任何需要用于構(gòu)建
    SecurityManager的配置
    [users]
    # 'users' 分段用于簡(jiǎn)單部署
    # 當(dāng)你只需要少量靜態(tài)定義的用戶(hù)帳戶(hù)時(shí)
    [roles]
    # 'roles' 分段用于簡(jiǎn)單部署
    # 當(dāng)你只需要少量靜態(tài)定義的角色時(shí)
    [urls] # 'urls' 分段用于web應(yīng)用程序中作基于url的基礎(chǔ)安全控制
    # 我們會(huì)Web文檔中討論這個(gè)分段
    [main]
    [main]分段是你配置應(yīng)用程序SecurityManager實(shí)例,及其任何依賴(lài),如Realms.
    像SecurityManager或其依賴(lài)這樣的配置對(duì)象實(shí)例聽(tīng)起來(lái)對(duì)于INI來(lái)說(shuō),是一件困難的事情,因?yàn)樵谶@里我們只能使用name/value對(duì).
    但是通過(guò)一點(diǎn)點(diǎn)的約定和對(duì)對(duì)象圖的理解,你會(huì)發(fā)現(xiàn)你可以做得很好。Shiro用這些假設(shè)使一個(gè)簡(jiǎn)單的配置機(jī)制成為了可能。
    我們常喜歡把這種方法稱(chēng)為“窮人的“依賴(lài)注入,雖然不比全面的Spring/ Guice / JBoss的XML文件強(qiáng)大,但你會(huì)發(fā)現(xiàn)它沒(méi)有過(guò)多的復(fù)雜性。
    當(dāng)然也可使用其他的配置機(jī)制,但對(duì)于Shiro來(lái)說(shuō),他們不是必須的.
    只是為了刺激你的欲望,這里有一個(gè)有效的[main]配置實(shí)例:
    [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
    定義對(duì)象
    細(xì)想下面的[main] 分段片斷:
    [main] myRealm = com.company.shiro.realm.MyRealm ...
    這行實(shí)例化了一個(gè)com.company.shiro.realm.MyRealm類(lèi)型的新對(duì)象,并為了以后的引用和配置,使其在名稱(chēng)myRealm名稱(chēng)下可用.
    如果實(shí)例的對(duì)象實(shí)現(xiàn)了org.apache.shiro.util.Nameable接口, 那么可在對(duì)象上使用名稱(chēng)值(myRealm)來(lái)調(diào)用Nameable.setName.
    設(shè)置對(duì)象屬性
    原始類(lèi)型值
    簡(jiǎn)單原始類(lèi)型屬性可以使用=號(hào)來(lái)賦值:
    ...
    myRealm.connectionTimeout = 30000
    myRealm.username = jsmith ...
    這些行的配置轉(zhuǎn)換成方法調(diào)用為:
    ...
    myRealm.setConnectionTimeout(30000);
    myRealm.setUsername(
    "jsmith"); ...
    這怎么可能呢?它假定所有的對(duì)象都是java bean兼容的POJOs。
    在后臺(tái),Shiro默認(rèn)使用Apache Commons BeanUtils來(lái)設(shè)置這些屬性。所以盡管INI值是文本,BeanUtils知道如何將字符串值的原始類(lèi)型,然后調(diào)用相應(yīng)的JavaBean的setter方法。
    引用值
    如果需要設(shè)置的值不是原始類(lèi)型而是其它對(duì)象呢? 你可以使用$來(lái)引用先前定義的實(shí)例.例如:
    ...
    sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
    ...
    myRealm.credentialsMatcher = $sha256Matcher ...
    這會(huì)簡(jiǎn)單地定位名為sha256Matcher 的對(duì)象,然后使用 BeanUtils 在 myRealm 實(shí)例上來(lái)設(shè)置這個(gè)對(duì)象(通過(guò)調(diào)用myRealm.setCredentialsMatcher(sha256Matcher)方法).
    內(nèi)嵌屬性
    在=的左邊使用點(diǎn)號(hào)分隔法來(lái)對(duì)內(nèi)嵌屬性進(jìn)行設(shè)值.例如:
    ...
    securityManager.sessionManager.globalSessionTimeout = 1800000 ...
    用BeanUtils轉(zhuǎn)換成下面的邏輯為:
    securityManager.getSessionManager().setGlobalSessionTimeout(1800000);
    圖的遍歷可以根據(jù)需要來(lái)設(shè)置深度: object.property1.property2....propertyN.value = blah
    BeanUtils Property Support
    Any property assignment operation supported by the BeanUtils.setProperty method will work in Shiro's [main] section, including set/list/map element assignments.
    See the Apache Commons BeanUtils Website and documentation for more information.
    Byte 數(shù)組值
    由于原始字節(jié)數(shù)組不能文本格式進(jìn)行指定,我們必須使用字節(jié)數(shù)組的文本編碼.這些值可以通過(guò)Base64 編碼字符串(默認(rèn))或 Hex編碼字符串進(jìn)行指定.
    默認(rèn)是Base64 ,因?yàn)?Base64編碼需要更少的實(shí)際文本來(lái)表現(xiàn)值- 它有一個(gè)更大的編碼字母表,這意味著你的令牌更短(對(duì)于文本配置更好).
    # The 'cipherKey' attribute is a byte array. By default, text values
    #
    for all byte array properties are expected to be Base64 encoded:
    securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA== ...
    然而,如果你選擇使用Hex編碼, 你必須使用0x ('zero' 'x')作為字符串的前輟:
    securityManager.rememberMeManager.cipherKey = 0x3707344A4093822299F31D008
    Collection屬性
    Lists, Sets 和Maps 也可以像其它屬性來(lái)設(shè)置 -要么直接設(shè)置,要么通過(guò)內(nèi)嵌屬性設(shè)置. 對(duì)于sets和Lists,只需要以逗號(hào)分隔來(lái)指定值或?qū)ο笠玫募希?/div>
    sessionListener1 = com.company.my.SessionListenerImplementation
    ...
    sessionListener2 = com.company.my.other.SessionListenerImplementation
    ...
    securityManager.sessionManager.sessionListeners = $sessionListener1, $sessionListener2
    對(duì)于Maps,你可以以逗號(hào)分隔的key-value對(duì)列表來(lái)指定, 每個(gè)key-value對(duì)都由冒號(hào)來(lái)分隔
    object1 = com.company.some.Class
    object2 = com.company.another.
    Class
    ...
    anObject = some.class.with.a.Map.property
    anObject.mapProperty = key1:$object1, key2:$object2
    In the above example, the object referenced by $object1 will be in the map under the String key key1, i.e. map.get("key1") returns object1. You can also use other objects as the keys:
    anObject.map = $objectKey1:$objectValue1, $objectKey2:$objectValue2 ...
    注意事項(xiàng)
    順序影響
    雖然INI格式非常方便和易于理解,但它并沒(méi)有像其它基于text/XML配置機(jī)制強(qiáng)大. 使用上述機(jī)制時(shí),要理解的最重要的事情是順序帶來(lái)的影響.
    小心
    Each object instantiation and each value assignment is executed in the order they occur in the 在每個(gè)[main] 分段中,每個(gè)對(duì)象實(shí)例和及值的分配都是出現(xiàn)順序來(lái)執(zhí)行的.
    這些行最終都會(huì)轉(zhuǎn)換成對(duì)avaBeans getter/setter 方法的調(diào)用,且這些方法也是按相同順序來(lái)調(diào)用的!在編寫(xiě)配置時(shí),要當(dāng)心.
    覆蓋實(shí)例
    任何對(duì)象都可以通過(guò)配置文件后面新定義的實(shí)例來(lái)覆蓋.因此對(duì)于下面的例子,第二個(gè)myRealm定義將覆蓋前面一個(gè):
    ...
    myRealm = com.company.security.MyRealm
    ...
    myRealm = com.company.security.DatabaseRealm ...
    譯者注:如果這兩個(gè)key在同一個(gè)段內(nèi),就與先前的描述違背了.
    這個(gè)導(dǎo)致myRealm成為com.company.security.DatabaseRealm的實(shí)例,先前的實(shí)例將不再使用(垃圾回收掉).
    默認(rèn)SecurityManager
    你可能已經(jīng)注意到了,上面的例子中沒(méi)有定義 SecurityManager 實(shí)例, 我們跳到右邊只設(shè)置了一個(gè)內(nèi)嵌屬性:
    myRealm = ...
    securityManager.sessionManager.globalSessionTimeout = 1800000 ...
    這是因?yàn)閟ecurityManager實(shí)例是特定的一個(gè)- 它已經(jīng)為你實(shí)例化好了,因此你不需要了解具體的SecurityManager實(shí)現(xiàn).
    當(dāng)然,如果你想指定你自己的實(shí)現(xiàn),你可以定義你的實(shí)現(xiàn)來(lái)進(jìn)行覆蓋:
    ... securityManager = com.company.security.shiro.MyCustomSecurityManager ...
    當(dāng)然,極少需要這樣- Shiro的SecurityManager實(shí)現(xiàn)是可充分定制的,通常可以按任何需要進(jìn)行配置.
    [users]
    [users] 分段允許你定義一些靜態(tài)用戶(hù)帳戶(hù)集合. 這在一個(gè)非常小的用戶(hù)帳戶(hù)或用戶(hù)帳戶(hù)不需要在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建環(huán)境中有用. 下面是例子:
    [users]
    admin = secret lonestarr = vespa, goodguy, schwartz darkhelmet = ludicrousspeed, badguy, schwartz
    Automatic IniRealm
    只定義非空的[users]或[roles]分段會(huì)自動(dòng)觸發(fā)org.apache.shiro.realm.text.IniRealm實(shí)例的創(chuàng)建,并使得[main]分段下的iniRealm可用.
    你可以像上面一樣來(lái)配置其它任何對(duì)象.
    行格式
    [users]分段中的每行都有下面的格式:
    username = password, roleName1roleName2, ..., roleNameN
    • 等號(hào)左邊的值是用戶(hù)名
    • 等號(hào)右邊的第一個(gè)值是用戶(hù)的密碼.密碼是必須的.
    • 密碼后面以逗號(hào)分隔的值是為用戶(hù)分配的角色.角色名稱(chēng)是可選的.
    密碼加密
    如果你不想[users]分段中的密碼是明文的,你可以使用你喜歡的hash算法(MD5, Sha1, Sha256)來(lái)對(duì)其加密,并使用結(jié)果字符串來(lái)作為密碼值.
    默認(rèn)情況下期望的密碼字符串是Hex編碼的,但你可以使用Base64編碼來(lái)代替(見(jiàn)下面).
    Easy Secure Passwords
    為了節(jié)省時(shí)間, 你可以使用Shiro的 Command Line Hasher, 它會(huì)將密碼hash成其它類(lèi)型的資源.對(duì)于加密 INI [users] 密碼是非常方便的.
    一旦你指定了哈稀化的文本值, 你必須告訴Shiro它們是加密的. 你可為隱式創(chuàng)建的iniRealm 在[main]分段中來(lái)配置適當(dāng)?shù)膶?duì)應(yīng)你指定的哈希算法的CredentialsMatcher實(shí)現(xiàn):
    [main]
    ...
    sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
    ...
    iniRealm.credentialsMatcher = $sha256Matcher
    ...
    [users]
    # user1 = sha256-hashed-hex-encoded password, role1, role2,
    ...
    user1 = 2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b, role1, role2, ...
    你可在CredentialsMatcher上配置任何屬性,如反映哈稀策略的對(duì)象,例如, 是否使用鹽(salting)或者執(zhí)行多少次hash迭代.
    參考org.apache.shiro.authc.credential.HashedCredentialsMatcher JavaDoc來(lái)更好的理解哈稀策略.
    例如,如果你想對(duì)用戶(hù)密碼使用Base64編碼來(lái)代替默認(rèn)的Hex,你可以按如下來(lái)指定:
    [main]
    ...
    # true = hex, false = base64:
    sha256Matcher.storedCredentialsHexEncoded =
    false
    [roles]
    [roles]分段允許你使用Permissions 來(lái)關(guān)聯(lián)定義在[users]分段中的角色.
    再次說(shuō)明,這對(duì)于少量角色或在運(yùn)行時(shí)不需要?jiǎng)討B(tài)創(chuàng)建角色的環(huán)境有用.下面是一個(gè)例子:
    [roles]
    # 'admin' 的角色擁有所有權(quán)限, 使用通配符'*'來(lái)表示 admin = *
    # 'schwartz' 角色可在任何lightsaber上執(zhí)行任何操作(*): schwartz = lightsaber:*
    # 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with # license plate 'eagle5' (instance specific id) goodguy = winnebago:drive:eagle5
    行格式
    [roles]分段中的每行必須按下面的格式來(lái)定義role-to-permission(s) key/value:
    rolename = permissionDefinition1permissionDefinition2, ..., permissionDefinitionN
    這里的permissionDefinition 是任意的字符串,但大部分人為了靈活性,會(huì)使用符合org.apache.shiro.authz.permission.WildcardPermission 格式的字符串. 參考Permissions 文檔來(lái)了解更多關(guān)于權(quán)限的信息
    內(nèi)部逗號(hào)
    注意,如果在單個(gè)permissionDefinition 中存在逗號(hào)分隔符(如. printer:5thFloor:print,info),你必須使用雙引號(hào),以避免解析錯(cuò)誤:
    "printer:5thFloor:print,info"
    無(wú)權(quán)限的角色
    如果角色不需要關(guān)聯(lián)權(quán)限,那么則不需要在[roles]分段中列出.如果角色不存在,只需要在[users]分段中定義角色就足夠創(chuàng)建角色了.
    [urls]
    這個(gè)分段及其它選項(xiàng)將在Web章節(jié)中進(jìn)行講解.
    posted on 2016-08-18 17:32 胡小軍 閱讀(2514) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Apache Shiro

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 中国videos性高清免费| 日韩成人精品日本亚洲| 亚洲高清视频在线| 亚洲av日韩精品久久久久久a| 免费国产va在线观看| 国产午夜不卡AV免费| 国产免费不卡视频| 日本特黄特色免费大片| 国产日产亚洲系列最新| 日韩精品亚洲人成在线观看| 中中文字幕亚洲无线码| 污视频网站免费观看| 日韩免费视频一区二区| 无码日韩精品一区二区免费| 免费一级毛片清高播放| 亚洲AV福利天堂一区二区三| 久久国产亚洲精品| 国产精品永久免费视频| 免费黄色福利视频| 亚洲国产香蕉人人爽成AV片久久 | 亚洲免费一区二区| 久久丫精品国产亚洲av不卡 | 亚洲熟妇无码爱v在线观看| 亚洲国产AV一区二区三区四区| 亚洲精品视频免费| 免费观看激色视频网站bd| 免费又黄又爽又猛的毛片| 亚洲小视频在线观看| 亚洲AV女人18毛片水真多| 国产免费AV片在线观看| 好吊妞在线成人免费| 亚洲精品亚洲人成在线观看| 在线综合亚洲中文精品| 国产亚洲精品免费视频播放| 毛片a级毛片免费观看品善网| 国产亚洲人成A在线V网站| 456亚洲人成影院在线观| 国产线视频精品免费观看视频| 成人免费无码大片A毛片抽搐| 亚洲αv在线精品糸列| 男人的天堂av亚洲一区2区|