[翻譯-Shiro]-10分鐘教會你Apache Shiro

最近在研究Apache Shiro準備將自認爲比較重要的資料翻譯成中文(明天去拔牙,嗚嗚)。時間容許的狀況下會盡量多的翻譯 html

前言 java

歡迎來到Apache Shiro 10分鐘之旅! web

但願經過這個簡單、快速的示例,可讓你對應用程序中使用Shiro有個深刻的瞭解。嗯,10分鐘你應該能夠搞定它。 apache

概述 api

Apache Shiro是什麼? 安全

Apache Shiro一個功能強大,使用簡單的Java安全框架,它爲開發人員提供一個直觀而全面的認證,受權,加密及會話管理的解決方案。 服務器

實際上,Shiro的主要功能是管理應用程序中與安全相關的所有,同時儘量支持多種實現方法。Shiro是創建在完善的接口驅動設計和麪向對象原則之上的,支持各類自定義行爲。Shiro提供的默認實現,使其能完成與其餘安全框架一樣的功能,這不也是咱們一直努力想要獲得的嗎! session

那麼Apache Shiro能用來作什麼呢? 框架

不少,不少,嘿嘿。可是不在快速指南中作介紹,若是你想知道,那怎麼辦呢?去這裏找尋你的答案吧。固然若是你還想知道咱們何時,以及爲何要「創造」Shiro,去看看Shrio的歷史和使命吧。 ide

OK,如今讓咱們動手作點兒什麼吧。

注:Shiro能夠在任何環境下運行,小到最簡單的命令行應用,大到大型的企業應用以及集羣應用。可是咱們準備在快速指南中使用最最簡單的main方法的方式,讓你對Shiro的API有個感官的認識。

下載

  1. 確保已經安裝了JDK1.5+和Maven2.2+
  2. 這裏下載最新已發佈的源碼。例子中咱們使用1.1.0發佈版本。
  3. 解壓源代碼
  4. 進入快速指南文件夾

    cd shiro-root-1.1.0/samples/quickstart

  5. 運行快速指南

    mvn compile exec:java

過程當中會輸出日誌信息,用來告訴你正在進行的是什麼,最後退出執行。能夠在這裏「samples/quickstart/src/main/java/Quickstart.java 」找到源碼,也能夠進行修改,記得修改後運行「mvn compile exec:java 」便可。

Quickstart.java

Quickstart.java中包含剛剛咱們提到的全部內容(認證、受權等等),經過這個簡單的示例可讓你輕鬆的熟悉Shiro的API。那麼,讓咱們把Quickstart.java中的代碼,一點一點剖析,這樣便於理解它們的做用。 幾乎全部的環境下,均可以經過這種方式獲取當前用戶:

Subject currentUser = SecurityUtils.getSubject();

經過SecurityUtils.getSubject(),就能夠獲取當前Subject。Subject是應用中用戶的一個特定安全的縮影,雖然感受上直接使用User會更貼切,可是實際上它的意義遠遠超過了User。並且每一個應用程序都會有本身的用戶以及框架,咱們可不想和它們混淆在一塊兒,何況Subject就是安全領域公認的名詞。OK,咱們繼續。

在單應用系統中,調用getSubject()會返回一個Subject,它是位於應用程序中特定位置的用戶信息;在服務器中運行的狀況下(好比web應用),getSubject會返回一個位於當前線程或請求中的用戶信息。 如今你已經獲得了Subject對象,那麼用它能夠作什麼呢?

若是你想獲得應用中用戶當前Session的其餘參數,能夠這樣獲取Session對象:

Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );

這個Session對象是Shiro中特有的對象,它和咱們常用的HttpSession很是類似,但還提供了額外的東西,其中與HttpSession最大的不一樣就是Shiro中的Session不依賴HTTP環境(換句話說,能夠在非HTTP 容器下運行)。

若是將Shiro部署在web應用程序中,那麼這個Session就是基於HttpSession的。可是像QuickStart示例那樣,在非web環境下使用,Shiro則默認使用EnterpriseSessionManagment。也就是說,不論在應用中的任何一層使用一樣的API,卻不須要考慮部署環境,這一優勢爲應用打開一個全新的世界,由於應用中要獲取Session對象不再用依賴於HttpSession或者EJB的會話Bean。並且任何客戶端技術均可以共享session 數據。

如今你能夠獲得當前Subject和它的Session對象。那麼咱們如何驗證好比角色和權限這些東西呢?

很簡單,能夠經過已獲得的user對象進行驗證。Subject對象表明當前用戶,可是,誰纔是當前用戶呢?他們但是匿名用戶啊。也就是說,必須登陸才能獲取到當前用戶。沒問題,這樣就能夠搞定:

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.
    //(do you know what movie this is from? ;)
    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);
}

就是這樣,太簡單了吧!

那登陸失敗了怎麼處理呢?能夠經過捕獲各種異常,根據不一樣類型的異常作出不一樣的處理:

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?
}

能夠捕獲Shiro提供的各類異常,也能夠拋出自定義類異經常使用於處理Shiro未考慮到的狀況。預知詳情,能夠去了解AuthenticationException JavaDoc

提示:最安全的作法是將登陸失敗的消息告知用戶,你總不會幫助攻擊者入侵你的系統吧!

OK,如今已經擁有一個登陸用戶了,咱們還能作點兒什麼呢?

比方說,他們是誰:

//print their identifying principal (in this case, a 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.");
}
固然,還能夠進行功能強大的實例級別的權限驗證。經過它能夠判斷用戶是否有訪問特定類型實例的權限:

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(); //removes all identifying information and invalidates their session too.

這些就是使用Apache Shiro開發應用的核心了,固然,Apache Shiro已將將不少複雜的東西封裝在內部了,可是如今它就是這麼簡單。

你會有疑問吧,用戶登陸時,誰負責把用戶信息(用戶名、密碼、角色、權限等)取出來,還有運行時,誰負責安全認證呢?固然由你決定了啊。經過將一個實現了Shiro中的Realm的Reaml配置到Shiro中便可。

至於如何配置很大程度上取決於你的運行時環境,好比在單應用、web應用、基於Spring或JEE 容器的應用或者組合模式中使用Shiro,配置都有所不一樣。如何配置已經超出QuickStart示例的範圍,由於它的主要目的是幫助你熟悉Shiro的API和概念。

若是想進一步瞭解Shiro,能夠看看Authentication GuideAuthorization Guide。也能夠查看其餘文檔(特別是Reference Manual),這裏能夠解決你的各類疑問。

感謝一路同行,但願你能喜歡使用Apache Shiro。

相關文章
相關標籤/搜索