當前用戶
現在我們能夠開始做一些我們真正關心的事情——執行安全操作,
當保護我們的應用程式時,我們對自己可能提出的最為相關的問題是“當前用戶是誰”或“當前用戶是否被允許做XXX”,
當我們撰寫代碼或設計用戶介面時,問這些問題是很常見的:應用程式通常是基于用戶的背景情況建立的,且你想基于每個用戶標準體現(保障)功能,因此,對于我們考慮應用程式安全的最自然的方式是基于當前用戶,
Shiro的API使用它的Subject概念從根本上代表了“當前用戶”的概念,
幾乎在所有的環境中,你可以通過下面的呼叫獲取當前正在執行的用戶:
Subject currentUser = SecurityUtils.getSubject();
使用 SecurityUtils.getSubject(),我們可以獲得當前正在執行的Subject,Subject是一個安全術語,它基本上的意思是“當前正在執行的用戶的特定的安全視圖”,它并沒有被稱為"User"是因為"User"一詞通常和人類相關聯,
在安全界,術語"Subject"可以表示為人類,而且可是第三方行程,cron job,daemonaccount,或其他類似的東西,它僅僅意味著“該事物目前正與軟體互動”,
對于大多數的意圖和目的,你可以把 Subject 看成是 Shiro 的"User"概念,
getSubject()在一個獨立的應用程式中呼叫,可以回傳一個在應用程式特定位置的基于用戶資料的Subject,并且在服務器環境中(例如,Web 應用程式),它獲取的Subject 是基于關聯了當前執行緒或傳入請求的用戶資料的,
當前用戶會話
現在你擁有了一個Subject,你能拿它來做什么?
如果你想在應用程式的當前會話中使事物對于用戶可用,你可以獲得他們的會話:
Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );
Session是一個Shiro的特定實體,它提供了大部分你經常與 HttpSessoins使用的東西,除了一些額外的好處以及一
個巨大的區別:它不需要一個 HTTP 環境!
如果在一個Web應用程式內部部署,默認的Session將會是基于 HttpSession 的,但在一個非 Web 環境中,像這
個簡單的教程應用程式,Shiro將會默認自動地使用它的 Enterprise Session Management,這意味著你會使用相同的API在你的應用程式,在任何層,不論部署環境!這開辟了應用程式的新世界,由于任何需要會話的應用程式不必再被強制使用HttpSession或EJB Stateful Session Beans,并且,任何客戶端技術現在能夠共享會話資料,
因此,現在你能獲取一個Subject以及他們的Session,如果他們被允許做某些事,如對角色和權限的檢查,像“檢查”真正有用的地方在哪呢?
權限檢查
嗯,我們只能為一個已知的用戶做這些檢查,我們上面的 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 可能不提供的,請參見AuthenticationException JavaDoc 獲取更多,
Handy Hint
最安全的做法是給普通的登錄失敗訊息給用戶,因為你當然不想幫助試圖闖入你系統的攻擊者,
好了,到現在為止,我們已經有了一個登錄用戶,我們還能做些什么?
比方說,他們是是誰:
//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.
總結
希望此次推出的教程幫助您了解如何在一個基本的應用程式設定 Shiro 以及 Shiro 的主要設計理念,
關注公眾號Java技術堆疊回復"面試"獲取我整理的2020最全面試題及答案,
推薦去我的博客閱讀更多:
1.Java JVM、集合、多執行緒、新特性系列教程
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
4.Java、后端、架構、阿里巴巴等大廠最新面試題
覺得不錯,別忘了點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/158279.html
標籤:Java
上一篇:Refresh Java
