Apache Shiro 簡介

來源:互聯網
上載者:User

標籤:des   http   io   ar   os   使用   sp   java   for   

Apache Shiro 是一個架構,可用於身分識別驗證和授權。本文提供了幾個樣本用來展示如何在 Java™ 應用程式中使用 Shiro 並給出了如何在一個 Grails web 應用程式中使用它的概述。為了從本文中最大限度地受益,您應該習慣於建立 Java 應用程式並安裝了如下的幾個組件:

  • Java 1.6 JDK
  • Grails(用來運行這些 web 應用程式樣本)
常用縮減詞
  • API: API
  • HTTP: 超文字傳輸通訊協定 (HTTP)
  • JAR: Java 檔案檔案
  • JDBC: Java 資料庫連接
  • JDK: Java 開發套件
  • LDAP:輕量級目錄訪問協議
身分識別驗證和授權

在對系統進行安全保障時,有兩個安全性元素非常重要:身分識別驗證和授權。雖然這兩個術語代表的是不同的含義,但出於它們在應用程式安全性方面各自的角色考慮,它們有時會被交換使用。

身分識別驗證 指的是驗證使用者的身份。在驗證使用者身份時,需要確認使用者的身份的確如他們所聲稱的那樣。在大多數應用程式中,身分識別驗證是通過使用者名稱和密碼的組合完成的。只要使用者選擇了他人很難猜到的密碼,那麼使用者名稱和密碼的組合通常就足以確立身份。但是,還有其他的身分識別驗證方式可用,比如指紋、認證和產生鍵。

一旦身分識別驗證過程成功地建立起身份,授權 就會接管以便進行訪問的限制或允許。 所以,有這樣的可能性:使用者雖然通過了身分識別驗證可以登入到一個系統,但是未經過授權,不準做任何事情。還有一種可能是使用者雖然具有了某種程度的授權,卻並未經過身分識別驗證。

在為應用程式規劃安全性模型時,必須處理好這兩個元素以確保系統具有足夠的安全性。身分識別驗證是應用程式常見的問題(特別是在只有使用者和密碼組合的情況下),所以讓架構來處理這項工作是一個很好的做法。合理的架構可提供經過測試和維護的優勢,讓您可以集中精力處理業務問題,而不是解決其解決方案已經實現的問題。

Apache Shiro 提供了一個可用的安全性架構,各種客戶機都可將這個架構應用於它們的應用程式。本文中的這些例子旨在介紹 Shiro 並著重展示對使用者進行身分識別驗證的基本任務。

 

回頁首

瞭解 Shiro

Shiro 是一個用 Java 語言實現的架構,通過一個簡單易用的 API 提供身分識別驗證和授權。使用 Shiro,您就能夠為您的應用程式提供安全性而又無需從頭編寫所有代碼。

來自 IBM 的總體身分識別驗證解決方案

白皮書 “Enhancing Identity Assurance across all Access Scenarios Cost Effectively with IBM ISS Identity and Access Management Services” 探討了一個跨各種商務應用程式和訪問情境的、完全整合的、企業範圍的、經濟高效的身分識別驗證解決方案。

這個解決方案提供了一個高度安全的集中式的身分識別驗證基礎設施,通過它的 API 或諸如 RADIUS 或 LDAP 這樣的標準身分識別驗證協議可很容易地與各種應用程式或 IT 基礎設施組件整合。它支援廣泛的軟硬體或基於手機的身分識別驗證令牌,在選擇具體的驗證方法方面提供了最大限度的靈活性。

由於 Shiro 提供具有諸多不同資料來源的身分識別驗證,以及 Enterprise Session Management,所以是實現單點登入(SSO)的理想之選 — 大型企業內的一個理想特性,因為在大型企業內,使用者需要在一天內經常登入到並使用不同系統。這些資料來源包括 JDBC、LDAP、 Kerberos 和 Microsoft® Active Directory® Directory Services (AD DS)。

Shiro 的 Session 對象允許無需 HttpSession 即可使用一個使用者會話。通過使用一個通用的 Session 對象,即便該代碼沒有在一個 Web 應用程式中運行,仍可以使用相同的代碼。沒有對應用伺服器或 Web 應用程式伺服器會話管理的依賴,您甚至可以在命令列環境中使用 Shiro。換言之,使用 Shiro 的 API 編寫的代碼讓您可以構建串連到 LDAP 伺服器的命令列應用程式並且與 web 應用程式內用來訪問 LDAP 伺服器的代碼相同。

下載並安裝 Shiro

Shiro 是預構建的二進位發行版。您可以下載 Shiro JAR 檔案或將各項放入到 Apache Maven 或 Apache Ivy 來自動安裝這些檔案。本例使用 Ivy 下載 Shiro JAR 檔案以及其他所需要的庫,指令碼很簡單,如 清單 1 所示。

清單 1. Apache Ivy 檔案和 Apache Ant 指令碼
<?xml version="1.0" encoding="UTF-8"?><ivy-module version="2.0"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">    <info organisation="com.nathanagood.examples" module="shirotest" />    <configurations>        <conf name="dist" description="Dependency configuration for distribution." />    </configurations>    <dependencies>        <dependency org="commons-logging" name="commons-logging"            rev="1.1.1" conf="dist->default" />        <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.5.8"            conf="dist->default" />        <dependency org="org.apache.shiro" name="shiro-core" rev="1.0.0-incubating"            conf="dist->default" />        <dependency org="org.apache.shiro" name="shiro-web" rev="1.0.0-incubating"            conf="dist->default" />    </dependencies></ivy-module><project name="shiroTestApp" default="usage" basedir="."     xmlns:ivy="antlib:org.apache.ivy.ant">    <property name="project.lib" value="lib" />    <path id="ivy.task.path">        <fileset dir="${basedir}/ivy-lib">            <include name="**/*.jar" />        </fileset>    </path>    <target name="resolve">        <taskdef resource="org/apache/ivy/ant/antlib.xml"             uri="antlib:org.apache.ivy.ant" classpathref="ivy.task.path" />        <ivy:resolve />        <ivy:retrieve pattern="${project.lib}/[conf]/[artifact].[ext]" sync="true" />    </target>    <target name="usage">        <echo message="Use --projecthelp to learn more about this project" />    </target></project>

有關使用 Ivy 的更多資訊,參見 參考資料。如果不使用 Maven 或 Ivy,可用從本文 參考資料 部分提供的下載網站下載這些 Shiro JAR 檔案。

下載了這些庫後,只需將它們添加到 CLASSPATH。編寫 清單 2 內所示的簡單代碼,它獲得對目前使用者的一個引用並報告說使用者未經身分識別驗證。(使用 Subject 類來代表此使用者。)

清單 2. ShiroTest Java 類
package com.nathanagood.examples.shirotest;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class ShiroTest {    private static Logger logger = LoggerFactory.getLogger(ShiroTest.class);    public static void main(String[] args) {        // Using the IniSecurityManagerFactory, which will use the an INI file        // as the security file.        Factory<org.apache.shiro.mgt.SecurityManager> factory =             new IniSecurityManagerFactory("auth.ini");        // Setting up the SecurityManager...        org.apache.shiro.mgt.SecurityManager securityManager             = factory.getInstance();        SecurityUtils.setSecurityManager(securityManager);        Subject user = SecurityUtils.getSubject();        logger.info("User is authenticated:  " + user.isAuthenticated());    }}

添加了此代碼後,建立一個名為 auth.ini 的檔案。此時,這個檔案是空白的;它的作用只是為了能夠在這裡運行這個樣本來檢查代碼是否正常工作。

建立檔案後,運行這個樣本。應該會看到包含了一個 INFO 登入訊息的輸出,報告說使用者沒有登入。

SecurityUtils 對象是一個 singleton,這意味著不同的對象可以使用它來獲得對目前使用者的訪問。一旦成功地設定了這個SecurityManager,就可以在應用程式不同部分調用 SecurityUtils.getSubject() 來獲得目前使用者的資訊。

 

回頁首

使用者令牌

在 Shiro 術語中,令牌 指的是一個鍵,可用它登入到一個系統。最基本和常用的令牌是 UsernamePasswordToken,用以指定使用者的使用者名稱和密碼。

UsernamePasswordToken 類實現了 AuthenticationToken 介面,它提供了一種獲得憑證和使用者的主體(帳戶身份)的方式。UsernamePasswordToken 適用於大多數應用程式,並且您還可以在需要的時候擴充 AuthenticationToken 介面來將您自己獲得憑證的方式包括進來。例如,可以擴充這個介面來提供您應用程式用來驗證使用者身份的一個關鍵檔案的內容。

 

回頁首

簡單的身分識別驗證

至此,這個簡單的樣本涵蓋的內容包括:啟動 Shiro SecurityManager、獲得目前使用者並記錄下使用者未經身分識別驗證。接下來的這個例子將會使用 UsernamePasswordToken 和儲存在 INI 檔案內的一個使用者記錄來展示如何通過使用者名稱和密碼進行身分識別驗證。

清單 3 內所示的 auth.ini 檔案現在包含了一個使用者記錄;這個記錄包含了使用者名稱和密碼。您可以在這個記錄內定義角色以及為應用程式提供授權。

清單 3. auth.ini 檔案
[users]bjangles = dance

現在,建立 前一節 中介紹的這個 UsernamePasswordToken 對象,如 清單 4 所示。

清單 4. 使用 UsernamePasswordToken 類
// snipped... same as before.public class ShiroTest {    private static Logger logger = LoggerFactory.getLogger(ShiroTest.class);    public static void main(String[] args) {        // Using the IniSecurityManagerFactory, which will use the an INI file        // as the security file.        Factory<org.apache.shiro.mgt.SecurityManager> factory =             new IniSecurityManagerFactory("auth.ini");        // Setting up the SecurityManager...        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();        SecurityUtils.setSecurityManager(securityManager);        Subject user = SecurityUtils.getSubject();        logger.info("User is authenticated:  " + user.isAuthenticated());                UsernamePasswordToken token = new UsernamePasswordToken("bjangles", "dance");                user.login(token);                logger.info("User is authenticated:  " + user.isAuthenticated());    }}

UsernamePasswordToken 對象由使用者名稱和密碼的組合執行個體化。隨後,令牌被傳遞至 Subject 類的 login() 方法。

再次運行這個樣本。注意到登入訊息現在報告說此使用者已經身分識別驗證。

要確保代碼正常工作且獲得的不是一個誤判,在代碼內更改密碼或更改這個 INI 檔案並再次運行此樣本。login() 方法現在會拋出一個IncorrectCredentialsException。在生產代碼內這個異常應被明確捕獲以便應用程式在使用者提供了不正確的代碼時能夠進行恰當的響應。

如果使用者不正確,login() 方法就會拋出一個 UnknownAccountException。我們既要考慮如何處理這個異常,但又不應向使用者提供太多資訊。一種常見的做法是不要向使用者提示使用者名稱有效、只有密碼不正確。這是因為如果有人試圖通過猜測獲得訪問,那麼您絕對不會想要暗示此人他所猜測的使用者名稱是正確的。

 

回頁首

用 LDAP 進行身分識別驗證

LDAP 是用來在 TCP/IP 上查詢目錄的一種協議。這些目錄可儲存有關使用者的任意數量的資訊,包括使用者識別碼、聯絡資訊以及群組成員等。LDAP 目錄對於公司的通訊錄很有用並被廣泛使用。

AD DS 是一種用於使用者和組管理的常見目錄,它支援 LDAP。 Shiro 不包含通用的 LDAP 安全域,但它卻包含了一個ActiveDirectoryRealm 對象,允許針對 LDAP 進行使用者的身分識別驗證。本例使用了在 INI 檔案內配置的 ActiveDirectoryRealm 對象來驗證使用者的身份。雖然 AD DS 與 LDAP 不同,但本文中使用的 Shiro 的這個版本並沒有內建通用的 LDAP 對象。

讓一個 LDAP 伺服器來測試本例要比編寫並運行樣本本身需要更多工作。如果您不能訪問一個 AD DS 伺服器,那麼可以考慮下載並安裝 Apache Directory 來提供一個 LDAP 伺服器的範例實現。Apache Directory 是用 Java 語言編寫的。同樣地,Apache Active Directory Studio 是一個 Eclipse 外掛程式,可用來瀏覽 LDAP 資料。它還具有一些範例資料,為您提供了一種捷徑來針對已知值編寫代碼,而又無需疑惑您遇到的問題是代碼問題還是資料問題。

清單 5 顯示了用來對儲存在 Apache Directory 內的一個使用者進行身分識別驗證所需的代碼。

清單 5. 使用 LDAP 進行身分識別驗證
// snipped...public class ShiroLDAPTest {    private static Logger logger = LoggerFactory.getLogger(ShiroLDAPTest.class);    /**     * @param args     */    public static void main(String[] args) {        // Using the IniSecurityManagerFactory, which will use the an INI file        // as the security file.        Factory<org.apache.shiro.mgt.SecurityManager> factory =             new IniSecurityManagerFactory("actived.ini");        // Setting up the SecurityManager...        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();        SecurityUtils.setSecurityManager(securityManager);        Subject user = SecurityUtils.getSubject();        logger.info("User is authenticated:  " + user.isAuthenticated());        UsernamePasswordToken token =         new UsernamePasswordToken(            "cn=Cornelius Buckley,ou=people,o=sevenSeas", "argh");        user.login(token);        logger.info("User is authenticated:  " + user.isAuthenticated());    }}

除了 INI 檔案名稱和使用者名稱及密碼之外,代碼與之前用 INI 檔案內的記錄進行身分識別驗證的代碼相同。這種類似性的出現是因為您可以使用 INI 檔案來配置 Shiro。用來設定 Shiro 針對 Apache Directory 進行身分識別驗證的這些 INI 記錄如 清單 6 所示。

清單 6. actived.ini 檔案
[main]activeDirectoryRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealmactiveDirectoryRealm.systemUsername = uid=admin,ou=systemactiveDirectoryRealm.systemPassword = secretactiveDirectoryRealm.searchBase = o=sevenSeas,ou=peopleactiveDirectoryRealm.url = ldap://localhost:10389

注意: 我使用 Apache Directory Studio 來將使用者的密碼更改為一個能放入測試代碼以確保它工作的值。

 

回頁首

運行一個 Grails web 應用程式

您可以使用兩種基本技巧將 Shiro 應用到 web 應用程式。首先,您可以使用這個 API 來將這裡所展示的的代碼併入一個基礎 servlet。其次,您可以使用 Shiro 內建的 HTTP 過濾器。本例展示了第二種技巧,因為使用過濾器充分利用了內建 web 應用伺服器技術以及來自 Shiro 項目的預先編寫好的代碼。

本例顯示了如何使用 Grails 內的這些過濾器。Grails 是一個項目,旨在讓您通過使用一種慣例優先原則(convention-over-configuration)的方式儘快地編寫 Groovy web 應用程式。有關 Grails 的更多資訊,請參見 參考資料。

對於 Shiro 過濾器,您通常會手動地向 web.xml 檔案添加必需的過濾器項。但是,Grails 會在您每次啟動應用程式時產生 web.xml 檔案,因此不必手動修改 web.xml。

幸運的是,Grails 提供了外掛程式,可整合到 web.xml 產生過程並會讓您也可以參與在 web.xml 檔案內編寫這些項。如今,Grails 的可用外掛程式很多,包括面向 Shiro 的這個外掛程式。建議嘗試使用這個 Shiro Grails 外掛程式,它提供了幾個新的指令碼,運行這些指令碼可以建立不同的域和控制器。

或者,如果您更願意自己添加這些項並進行配置,您也可以編寫您自己的外掛程式。對於 Grails,編寫一個新的外掛程式很容易。要建立能將必需的 Shiro 過濾器項添加到 web.xml 檔案的 Grails 外掛程式,可以使用如下命令:

> grails create-plugin ShiroWebXml

建立了這個外掛程式項目後,編輯 ShiroWebXmlPlugin.groovy 檔案,並添加如 清單 7 所示的代碼。

清單 7. 樣本外掛程式
class ShiroWebXmlPlugin {      // snipped plugin details...    def doWithWebDescriptor = { xml ->       def filterElement = xml.‘filter‘       def lastFilter = filterElement[filterElement.size() - 1]       lastFilter + {           ‘filter‘ {               ‘filter-name‘("ShiroFilter")               ‘filter-class‘("org.apache.shiro.web.servlet.IniShiroFilter")               ‘init-param‘ {                   ‘param-name‘("config")                   ‘param-value‘("\n#config")               }           }       }       def filterMappingElement = xml.‘filter-mapping‘       def lastFilterMappingElement =            filterMappingElement[filterMappingElement.size() - 1]       lastFilterMappingElement + {           ‘filter-mapping‘ {               ‘filter-name‘("ShiroFilter")               ‘url-pattern‘("/*")               }           }       }}

當 Grails 執行這個 web.xml 檔案時,此代碼就會運行。

在啟動這個外掛程式應用程式測試它之前,先將用 Ivy 下載的 Shiro JAR 檔案複製到此外掛程式的 lib 檔案夾。有了 JAR 檔案後,用以下命令測試此外掛程式是否能正常工作:

grails run-app

如果此外掛程式應用程式成功啟動,您可以將它打包以便用在一個樣本項目中。要打包這個外掛程式,使用如下命令:

grails package-plugin

可以用如下命令安裝這個新的 ShiroWebXmlPlugin

cd myappgrails install-plugin /path/to/shiro-web-xml-1.0.zip
 

回頁首

故障排除

如果出現了 UnavailableSecurityManagerException,那麼可能是 SecurityManager 未被正確設定。在調用 getSubject() 方法之前,請確保它設在 SecurityUtils 對象上。

串連到 LDAP 伺服器可能會有些困難。如果得到一個 javax.naming.CommunicationException,那麼請檢查此 LDAP 伺服器的主機名稱和連接埠。即便您沒有使用 Apache Directory,Apache Directory Studio(可單獨安裝)也可以協助您排除串連故障以及名稱問題。

如果您沒有使用 Ant Ivy 指令碼來初始化您的環境,那麼有可能會得到丟失類的錯誤。即便沒有 Apache Commons Logging library (commons-logging),這個 INI 檔案樣本仍可運行,但是運行這個 LDAP 樣本會導致一個異常。這時,可以使用 Apace Commons BeanUtils 來解析這個 INI 檔案並設定對象上的值。

 

回頁首

結束語

Shiro 是 Apache Incubator 內的一個架構,可讓您嚮應用程式中添加身分識別驗證和授權。它支援不同的身分識別驗證儲存方式,比如 LDAP、Kerberos 和 AD DS。Shiro 最小限度的依賴性再加上它相對簡單的配置讓它成為了應用程式內安全性架構的一個很好的選擇。

轉自:http://www.ibm.com/developerworks/cn/web/wa-apacheshiro/#icomments

Apache Shiro 簡介

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.