10分鐘教會你Apache Shiro

jopen 10年前發布 | 20K 次閱讀 Shiro 安全相關 Apache Shiro

前言

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

希望通過這個簡單、快速的示例,可以讓你對應用程序中使用Shiro有個深入的了解。嗯,10分鐘你應該可以搞定它。

概述

Apache Shiro是什么?

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

實際上,Shiro的主要功能是管理應用程序 中與安全相關的全部,同時盡可能支持多種實現方法。Shiro是建立在完善的接口驅動設計和面向對象原則之上的,支持各種自定義行為。Shiro提供的默 認實現,使其能完成與其他安全框架同樣的功能,這不也是我們一直努力想要得到的嗎!

那么Apache Shiro能用來做什么呢?

很多,很多,嘿嘿。但是不在快速指南中做介紹,如果你想知道,那怎么辦呢?去這里找尋你的答案吧。當然如果你還想知道我們什么時候,以及為什么要"創造"Shiro,去看看Shrio的歷史和使命吧。

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),這里可以解決你的各種疑問。

 

轉自:http://www.turingbook.com/article/details/163

 


 

相關文章閱讀及下載:

 

Shiro1.1.0開發配置文檔

 

應用Shiro到Web Application

 

Apache Shiro 使用手冊

 

10分鐘教會你Apache Shiro

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!