1.簡介
歡迎來到Apache Shiro的10分鐘教程!
通過閱讀這個快速簡單的教程,您將充分了解開發(fā)人員如何在其應用程序中使用Shiro脊僚。而且你應該可以在10分鐘內(nèi)做到這一點只冻。
2.概覽
什么是Apache Shiro?
Apache Shiro是一個功能強大且易于使用的Java安全框架饿敲,為開發(fā)人員提供了一個直觀而全面的解決方案,用于身份驗證逛绵、授權(quán)怀各、加密和會話管理。
實際上术浪,它實現(xiàn)了管理應用程序安全性的所有方面瓢对,同時盡可能避免出現(xiàn)問題。它建立在完善的接口驅(qū)動設(shè)計和面向?qū)ο蟮脑瓌t之上胰苏,可以在任何你想象得到的地方實現(xiàn)自定義行為硕蛹。但是,對于所有事情來說碟联,默認情況下都是合理的妓美,這與應用程序安全性是一樣的。至少這是我們所追求的鲤孵。
Apache Shiro能做什么壶栋?
很多。但我們不想擴張“快速入門”的內(nèi)容普监。如果您想了解它可以為您做什么贵试,請查看我們的功能頁面琉兜。此外,如果您對我們?nèi)绾伍_始以及為什么存在感到好奇毙玻,請參閱Shiro History and Mission頁面豌蟋。
ok,現(xiàn)在我們來做一些事情吧桑滩!
注意:
Shiro可以在任何環(huán)境下運行梧疲,從最簡單的命令行應用程序到最大的企業(yè)Web和集群應用程序,但是我們將在這個快速入門(QuickStart)中使用一個簡單的"main"方法來完成一個最簡單的例子运准,以便可以獲得對API的感受幌氮。
3.下載
1)確保您安裝了JDK1.6+和Maven 3.0.3+。
2)從下載頁面下載最新的Shiro"源代碼分發(fā)"包胁澳。在這個例子中该互,我們使用1.3.2發(fā)行版本。
3)解壓源代碼包
$ unzip shiro-root-1.3.2-source-release.zip
4)進入quickstart目錄
$ cdshiro-root-1.3.2/samples/quickstart
5)運行QuickStart
$mvn compile exec:java
這個目標只會打印出一些日志消息韭畸,讓你知道發(fā)生了什么宇智,然后退出——(主要Maven構(gòu)建項目的過程,包括下載一些有關(guān)的組件胰丁,下載后随橘,下次運行就不再次下載了)。在閱讀本快速入門指南時隘马,請隨時查看samples / quickstart / src / main / java / Quickstart.java下的代碼太防。根據(jù)需要隨時更改該文件并運行上述mvn
compile exec:java命令。
【注:】
我這里在windows8下運行的酸员,JDK1.8+maven3.5;步驟同上讳嘱。
為了知道運行結(jié)果幔嗦,我在源代碼退出前位置加了一行代碼,以觀測效果:
log.info("\n====This is Quikstart
Exampel.It is done!====");//增加代碼行
結(jié)果示意圖:
4.Quickstart.java
上面引用的Quickstart.java文件包含了所有可以幫助您熟悉API的代碼×ぬ叮現(xiàn)在讓我們把它分成大塊邀泉,這樣你就可以很容易地理解發(fā)生了什么。
幾乎在所有環(huán)境中钝鸽,您都可以通過以下調(diào)用獲取當前正在執(zhí)行的用戶:
Subject currentUser =SecurityUtils.getSubject();
使用SecurityUtils.getSubject()汇恤,我們可以獲得當前正在執(zhí)行的Subject。主體只是應用程序用戶的特定安全"視圖"拔恰。我們實際上想稱它為'User(用戶)'因谎,因為這"有道理",但我們決定不這么干:太多的應用程序都有現(xiàn)存的API颜懊,它們已經(jīng)擁有自己的User類/框架财岔,我們不想與這些API沖突风皿。另外,在安全領(lǐng)域匠璧,術(shù)語Subject實際上是公認的命名法桐款。 ok,繼續(xù)...
獨立應用程序中的getSubject()調(diào)用夷恍,可能會根據(jù)特定于應用程序的位置中的用戶數(shù)據(jù)以及服務器環(huán)境(例如Web應用程序)返回相應Subject魔眨,并根據(jù)與當前線程或傳入請求關(guān)聯(lián)的用戶數(shù)據(jù)而獲取Subject? 。
現(xiàn)在你有一個主題酿雪,你可以用它做什么遏暴?
如果您想在應用程序的當前會話期間向用戶提供可用的內(nèi)容,則可以獲得他們的會話:
Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );
Session是一個Shiro特定的實例执虹,它給你提供了大多數(shù)習慣的常規(guī)HttpSession實例拓挥,但有一些額外的好處和一個很大的區(qū)別:它不需要HTTP環(huán)境!
如果在Web應用程序內(nèi)部署袋励,默認情況下會話將基于HttpSession侥啤。但是,在非Web環(huán)境中茬故,就像這個簡單的快速入門一樣盖灸,Shiro默認會自動使用它的企業(yè)會話管理。這意味著無論部署環(huán)境如何磺芭,您都可以在應用程序中的任何層中使用相同的API赁炎。這將打開一個全新的應用程序世界,因為任何需要會話的應用程序都不需要強制使用HttpSession或EJB Stateful Session Beans钾腺。而且徙垫,任何客戶端技術(shù)現(xiàn)在都可以共享會話數(shù)據(jù)。
所以現(xiàn)在你可以獲得一個Subject和他們的Session放棒。那些真正有用的東西比如檢查是否允許他們做事情姻报,比如檢查角色和權(quán)限?
那么间螟,我們只能對已知的用戶進行這些檢查吴旋。上面的Subject實例代表當前用戶,但誰是當前用戶厢破?其實荣瑟,他們是匿名的 - 也就是說,直到他們登錄至少一次摩泪。所以笆焰,讓我們這樣做:
if ( !currentUser.isAuthenticated() ) {
??? //以gui特定方式收集用戶主體和憑證-principalsand credentials
??? //如html表單的用戶名/密碼,X509證書加勤,OpenID等仙辟。
??? //我們將在這里使用用戶名/密碼示例同波,因為它是最常見的。
??? //(你知道這是什么電影嗎叠国?;)
???UsernamePasswordToken token = newUsernamePasswordToken("lonestarr", "vespa");
??? //this isall you have to do to support 'remember me' (no config - built in!):
???????? //這就是你需要做的所有事情以便來支持'記住我'(沒有配置 - 內(nèi)置N撮荨)
???token.setRememberMe(true);
???currentUser.login(token);
}
附上述代碼截圖(清晰些:)
就這樣!沒有比這更容易了粟焊。
但是冤狡,如果他們的登錄嘗試失敗呢?你可以捕捉各種具體的例外情況项棠,告訴你到底發(fā)生了什么悲雳,并允許你相應地處理和做出反應:
try {
???currentUser.login( token );
???//如果沒有例外,就是這樣香追,搞定合瓢!
} catch ( UnknownAccountException uae ) {
???//用戶名不在系統(tǒng)中,如何向他們顯示錯誤消息透典?
} catch ( IncorrectCredentialsException ice) {
???//密碼不匹配晴楔,是否再試?
} catch ( LockedAccountException lae ) {
???//該用戶名的帳戶被鎖定 - 無法登錄峭咒。如何顯示一條消息税弃?
}
???...更多類型的異常檢查——如果你想要...
} catch ( AuthenticationException ae ) {
???//意外情況 - 怎么處理?
}
附上述代碼截圖
您可以檢查許多不同類型的例外情況,或者拋出Shiro可能無法解釋的自定義異常情況凑队。有關(guān)更多信息则果,請參閱AuthenticationException JavaDoc。
提示:
安全最佳做法是為用戶提供通用登錄失敗消息提示漩氨,因為您不希望幫助攻擊者試圖進入系統(tǒng)西壮。
ok,到現(xiàn)在為止叫惊,我們有一個登錄用戶茸时。我們還能做什么?
讓我們看看他們是誰:
//打印他們的標識主體(在這種情況下是用戶名)
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." );
}
我們還可以看到他們是否有權(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 mastersonly.");
}
另外赋访,我們可以執(zhí)行非常強大的實例級權(quán)限檢查 - 查看用戶是否有權(quán)訪問特定類型實例的功能:
if ( currentUser.isPermitted("winnebago:drive:eagle5" ) ) {
???log.info("You are permitted to 'drive' the 'winnebago' with licenseplate (id) 'eagle5'.? " +
???????????????"Here are the keys - have fun!");
} else {
???log.info("Sorry, you aren't allowed to drive the 'eagle5'winnebago!");
}
小菜一碟,對吧缓待?
最后蚓耽,當用戶完成使用應用程序時,他們可以注銷:
currentUser.logout(); //刪除所有標識信息并使其會話無效旋炒。
那么步悠,這就是在應用程序開發(fā)人員級別使用Apache Shiro的核心。雖然有一些非常復雜的東西在引擎蓋下進行瘫镇,使得這項工作如此優(yōu)雅鼎兽,但這確實是它的全部答姥。
但是你可能會問自己,"但是誰負責在登錄時獲取用戶數(shù)據(jù)(用戶名和密碼谚咬,角色和權(quán)限等)鹦付,以及誰在運行時真正執(zhí)行這些安全檢查?"择卦,這么問就對了——你來做:通過實施 Shiro稱之為Realm的東西敲长,并將該Realm插入到Shiro的配置中來完成。
但是秉继,如何配置Realm很大程度上取決于您的運行時環(huán)境祈噪。例如,如果運行獨立應用程序尚辑,或者如果您有基于Web的應用程序辑鲤,或基于Spring或JEE容器的應用程序或其組合,這種類型的配置不在本快速入門的范圍之內(nèi)杠茬,因為它的目的是讓您對API和Shiro的概念感到滿意月褥。
當您準備好了解更多細節(jié)時,您一定要閱讀認證指南和授權(quán)指南澈蝙。然后可以轉(zhuǎn)到其他文檔吓坚,特別是參考手冊中,以回答任何其他問題灯荧。您也可能想要加入用戶郵件列表 - 您會發(fā)現(xiàn)我們有一個非常棒的社區(qū)礁击,只要有可能,他們都愿意提供幫助逗载。
感謝您的關(guān)注哆窿。我們希望您喜歡使用Apache Shiro!
我會持續(xù)發(fā)布一些Shiro安全框架的文章或教程厉斟。希望對你有幫助挚躯。
碼字辛苦啊——打個賞唄~ ^_*