<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 2. Tutorial 教程 # 2. Tutorial 教程 ## Your First Apache Shiro Application 第一個 Shiro 應用 如果你是 Apache Shiro 新手,這個簡短的教程將向您展示如何通過Apache Shiro 設置一個初始和非常簡單的安全應用程序。接下來我們將討論 Shiro 的核心概念,幫助你熟悉 Shiro 的設計和 API。 當你跟隨本教程時,如果你不想編輯文件,您可以獲得一個幾乎相同的示例作為參考。 選擇一個地址: - 在Apache Shiro 的 Subversion 存儲庫: <https://svn.apache.org/repos/asf/shiro/trunk/samples/quickstart/> - 在Apache Shiro 的源碼發布 samples/quickstart 目錄中。 源碼可以[下載](http://shiro.apache.org/download.html)。 - (*譯者注*:譯者也提供了自己的代碼,包含了中文注解,本章所含示例如下) - [示例1](https://github.com/waylau/apache-shiro-1.2.x-reference-demos/tree/master/shiro-tutorial) - [示例2](https://github.com/waylau/apache-shiro-1.2.x-reference-demos/tree/master/shiro-tutorial-1) - [示例3](https://github.com/waylau/apache-shiro-1.2.x-reference-demos/tree/master/shiro-tutorial-2) ### Setup 設置 在這個簡單的示例中,我們將創建一個非常簡單的命令行應用程序,它將運行并迅速退出,這樣你可以領略到 Shiro 的API。 *任何應用程序* *Apache Shiro設計從一開始就支持**任何**應用程序——從最小的命令行應用程序最大的集群 web 應用程序。對于本教程,盡管我們創建一個簡單的應用程序,你都知道運用相同的使用模式來進行應用程序創建或部署。* 本教程需要 Java 1.5 或更高版本。 我們還將使用 Apache [Maven](http://maven.apache.org/) 作為我們的構建工具,當然這對于 Apache Shiro 來說不是必須使用。你可能獲得 Shiro 的 jars,把他們以任何方式你喜歡到您的應用程序,例如也許使用Apache [Ant](http://ant.apache.org/) 和 [Ivy](http://ant.apache.org/ivy) 。 對于本教程,請確保您使用 Maven 2.2.1 或更高版本。為了測試 Maven 安裝是否正確,命令行下運行 mvn --version 并看到類似如下: ![](https://box.kancloud.cn/8015c7ad032971532089387f99d557d2_643x147.jpg) 現在,在你的文件系統中創建一個新目錄,例如, shiro-tutorial 作為項目名并在目錄下保存以下 Maven `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> ``` #### 教程中的 class 我們將運行一個簡單的命令行應用程序,因此我們將需要創建一個帶 `public static void main(String[] args)` 方法 Java 類。 包含 pom.xml 文件的同一個目錄下,創建一個\*src/main/java 子目錄。 在 src/main/java 創建一個 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); } } ``` 先不要管引入包的問題。下午將會很快提到。我們先測試下這個應用,會輸出 "My First Apache Shiro Application" 并且退出。 ### Test Run 測試運行 在教程項目的根目錄(如 shiro-tutorial )執行以下命令提示符中,輸入以下: > mvn compile exec:java 你就會看到我們的小教程應用程序的運行和退出。 您應當會看到類似于下面的輸出(*譯者注:*紅框中的內容) ![](https://box.kancloud.cn/62a44b6cc3af0a7271fdfdb53a644589_670x294.jpg) 我們已經驗證了應用程序成功運行——現在讓我們使 Apache Shiro。當我們繼續學習教程,每次我們添加更多的代碼之后,您可以運行 mvn compile exec:java 看到我們的變化的結果。 ### Enable Shiro 使用 使用 Shiro 要理解的第一件事情是 Shiro 幾乎所有的事情都和一個中心組件 SecurityManager 有關,對于那些熟悉 Java security 的人請注意:這和 java.lang.SecurityManager 不是一回事。 我們將在[Architecture章節](https://github.com/waylau/apache-shiro-1.2.x-reference/blob/master/I.%20Overview%20%E6%80%BB%E8%A7%88/3.%20Architecture%20%E6%9E%B6%E6%9E%84.md)詳細描述 Shiro 的設計,但現在有必要知道 Shrio SecurityManager 是程序中 Shiro 的核心,每一個程序都必定會存在一個 SecurityManager,所以,在我們這個示例程序中必須做的第一件事情是建立一個 SecurityManager 實例。 #### Configuration 配置 雖然我們可以直接對 SecurityManager 實例化,但在 Java 代碼中對Shiro 的 SecurityManager 所須的選項和內部組件進行配置會讓人感覺有點小痛苦--而將這些 SecurityManager 配置用一個靈活的配置文件實現就會簡單地多。 為此,Shiro 默認提供了一個基本的 INI 配置文件的解決方案,人們已經對龐大的 XML 文件有些厭倦了,而一個 INI 文件易讀易用,而且所依賴的組件很少,稍后你就會通過一個簡單易懂的示例明白 INI 在對簡單對象進行配置的時候是非常有效率的,比如 SecurityManager *多種配置選擇* *Shiro 的 SecurityManager 的實現和其所依賴的組件都是 JavaBean,所以可以用多種形式對 Shiro 進行配置,比如XML(Spring, JBoss, Guice, 等等),[YAML](http://www.yaml.org/), JSON, Groovy Builder markup,及其它,INI 只是 Shiro 一種最基本的配置方式,使得其可以在任何環境中進行配置比如在那些沒有以上配置形式的環境中。* ##### shiro.ini 在這個示例中我們使用一個 INI 文件來配置Shiro SecurityManager,首先,在 pom.xml 同目錄中創建一個src/main/resources子目錄,在該子目錄中創建一個 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 ``` 可以看到,在該配置文件中最基礎地配置了幾個靜態的帳戶,對我們這一個程序已經足夠了,在以后的章節中,將會看到如何使用更復雜的用戶數據比如數據庫、LDAP 和活動目錄等。 #### Referencing the Configuration 引用配置 現在我們已經定義了一個 INI 文件,我們可以在我們的示例程序中創建SecurityManager 實例了,將 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); } ``` 這就是我們要做的--僅僅使用三行代碼就把Shiro加進了我們的程序,就是這么簡單。 執行mvn compile exec:java 可以看到程序成功的運行(由于 Shiro 默認在 debug 或更底層才記錄日志,所以你不會看到任何 Shiro 的日志輸出--只要運行時沒有錯誤提示,你就可以知道已經成功了)。 上面所加入的代碼做了下面的事情: 1. 使用 Shiro 的 IniSecurityManagerFactory 加載了我們的shiro.ini 文件,該文件存在于 classpath 根目錄里。這個執行動作反映出 shiro 支持 [Factory Method Design Pattern(工廠模式)](http://en.wikipedia.org/wiki/Factory_method_pattern)。classpath:資源的指示前綴,告訴 shiro 從哪里加載 ini 文件(其它前綴,如 url:和 file: 也被支持)。 2\.factory.getInstance() 方法被調用,該方法分析 INI 文件并根據配置文件返回一個 SecurityManager 實例。 3\.在這個簡單示例中,我們將 SecurityManager 設置成了static (memory) singleton,可以通過 JVM 訪問,注意如果你在一個 JVM 中加載多個使用 shiro 的程序時不要這樣做,在這個簡單示例中,這是可以的,但在其它成熟的應用環境中,通常會將 SecurityManager 放在程序指定的存儲中(如在 web 中的 ServletContexct 或者 Spring、Guice、 JBoss DI 容器實例)中。 #### Using Shiro 使用 現在我們的 SecurityManager 已經準備好了,我們可以開始進行我們真正關心的事情--執行安全操作了。 為了保護我們的程序安全,我們或許問自己最多的問題就是“誰是當前的用戶?”或者“當前用戶是否允許做某件事?”通常我們會在寫代碼或者設計用戶接口的時候問這些問題:程序通常建立在用戶基礎上,程序功能展示(和安全)也基于每一個用戶。所以,通常我們考慮我們程序安全的方法也建立在當前用戶的基礎上,Shiro 的 API 提供了'the current user'概念,即 Subject。 在幾乎所有的環境中,你可以通過如下語句得到當前用戶的信息: ``` Subject currentUser = SecurityUtils.getSubject(); ``` 使用 SecurityUtils.getSubject(),我們可以獲取當前執行的Subject,Subject是一個安全術語意思是“當前運行用戶的指定安全視圖(a security-specific view of the currently executing user)”,這里并不稱之為“User”因為“User”這個詞通常和一個人相關,但在安全認證中,“Subject”可以認為是一個人,也可以認為是第三方進程、時鐘守護任務、守護進程帳戶或者其它。它可簡單描述為“當前和軟件進行交互的事件”,在大多數情況下,你可以認為它是一個“人(User)”。 在一個獨立的程序中調用 getSubject() 會在程序指定位置返回一個基于用戶數據的 Subject,在服務器環境(如 web 程序)中,它將獲取一個和當前線程或請求相關的基于用戶數據的 Subject。 現在你得到了Subject,你可以利用它做什么呢? 如果你針對該用戶希望一些事情在程序當前會話期內可行,你可以獲取他們的 session: ``` Session session = currentUser.getSession(); session.setAttribute( "someKey", "aValue" ); ``` Session 是 shiro 指定的一個實例,提供基本上所有 HttpSession 的功能,但具備額外的好處和不同:它不需要一個 HTTP 環境! 如果發布到一個 web 程序中,默認情況下 Session 將會使用HttpSession 作為基礎,但是,在一個非 web 程序中,比如該簡單示例程序中,Shiro 將自動默認使用它的 Enterprise Session Management,這意味著你可以在任何程序中使用相同的 API,而根本不需要考慮發布環境!這打開了一個全新的世界,從此任何需要 session 的程序不再需要強制使用 HttpSession 或者 EJB Stateful Session,并且,終端可以共享 session 數據。 現在你可以獲取一個 Subject 和它們的 Session,真正填充有用的代碼如檢測其是否被允許做某些事情如何?比如檢查其角色和權限? 我們只能對一個已知用戶做這些檢測,如上我們獲取 Subject 實例表示當前用戶,但是當前用戶是認證,嗯,他們是任何人--直到他們至少登錄一次,我們現在就做這件事情: ``` if ( !currentUser.isAuthenticated() ) { //收集用戶的主要信息和憑據,來自GUI中的特定的方式 //如包含用戶名/密碼的HTML表格,X509證書,OpenID,等。 //我們將使用用戶名/密碼的例子因為它是最常見的。. UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); //支持'remember me' (無需配置,內建的!): token.setRememberMe(true); currentUser.login(token); } ``` 就是這樣,不能再簡單了。 但如果登錄失敗了呢,你可以捕獲所有異常然后按你期望的方式去處理: ``` try { currentUser.login( token ); //無異常,說明就是我們想要的! } catch ( UnknownAccountException uae ) { //username 不存在,給個錯誤提示? } catch ( IncorrectCredentialsException ice ) { //password 不匹配,再輸入? } catch ( LockedAccountException lae ) { //賬號鎖住了,不能登入。給個提示? } ... 更多類型異常 ... } catch ( AuthenticationException ae ) { //未考慮到的問題 - 錯誤? } ``` 這里有許多不同類別的異常你可以檢測到,也可以拋出你自己異常。詳見 [AuthenticationException JavaDoc](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/AuthenticationException.html) *小貼士:* *最好的方式是將普通的失敗信息反饋給用戶,你總不會希望幫助黑客來攻擊你的系統吧。* 好,到現在為止,我們有了一個登錄用戶,接下來我們還可以做什么? 讓我們顯示他們是誰 ``` //打印主要信息 (本例子是 username): log.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." ); ``` 我們也可以判斷他們是否擁有某個角色: ``` if ( currentUser.hasRole( "schwartz" ) ) { log.info("May the Schwartz be with you!" ); } else { log.info( "Hello, mere mortal." ); } ``` 我們也可以判斷他們是否擁有某個特定動作或入口的權限: ``` 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."); } ``` 同樣,我們還可以執行非常強大的 instance-level (實例級別)的權限檢測,檢測用戶是否具備訪問某個類型特定實例的權限: ``` 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!"); } ``` 輕而易舉,是吧! 最后,當用戶不再使用系統,可以退出登錄: ``` currentUser.logout(); //清楚識別信息,設置 session 失效. ``` #### Final Tutorial class 最終的 class 在加入上述代碼后,下面的就是我們完整的文件,你可以自由編輯和運行它,可以嘗試改變安全檢測(以及INI配置): 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); // 獲取當前執行用戶: Subject currentUser = SecurityUtils.getSubject(); // 做點跟 Session 相關的事 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 + "]"); } // 登錄當前用戶檢驗角色和權限 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 (AuthenticationException ae) { //無定義?錯誤? } } //說出他們是誰: //打印主要識別信息 (本例是 username): log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //測試角色: if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //測試一個權限 (非(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."); } //一個(非常強大)的實例級別的權限: 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!"); } //完成 - 退出t! currentUser.logout(); System.exit(0); } } ``` ![](https://box.kancloud.cn/980b6be90f6867e538acd6a4c989d24a_675x327.jpg) ### 總結 非常希望這示例介紹能幫助你理解如何在基礎程序中加入 Shiro,并理解Shiro 的設計理念,Subject 和 SecurityManager。 但這個程序太簡單了,你可能會問自己,“如果我不想使用 INI 用戶帳號,而希望連接更為復雜的用戶數據源呢?” 解決這些問題需要更深入地了解 并理解Shiro 的架構和配置機制,我們將在下一節 [Architecture](https://github.com/waylau/apache-shiro-1.2.x-reference/blob/master/I.%20Overview%20%E6%80%BB%E8%A7%88/3.%20Architecture%20%E6%9E%B6%E6%9E%84.md) 中介紹。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看