shiro實戰系列(二)之入門實戰續

youcongtech發表於2018-06-04

下面講解基於實戰系列一,所以相關的java檔案獲取pom.xml及其log4j檔案同樣適用於本次講解。

一、Using Shiro

Using Shiro 現在我們的 SecurityManager 已經設定好並可以使用了,現在我們能夠開始做一些我們真正關心的事情——執行安 全操作。   當保護我們的應用程式時,我們對自己可能提出的最為相關的問題是“當前使用者是誰”或“當前使用者是否被允許做 XXX”。當我們編寫程式碼或設計使用者介面時,問這些問題是很常見的:應用程式通常是基於使用者的背景情況建立的, 且你想基於每個使用者標準體現(保障)功能。因此,對於我們考慮應用程式安全的最自然的方式是基於當前使用者。 Shiro 的 API 使用它的 Subject 概念從根本上代表了“當前使用者”的概念。

 

幾乎在所有的環境中,你可以通過下面的呼叫獲取當前正在執行的使用者:

 

    Subject  currentUser=SecurityUtils.getSubject();
        

使用 SecurityUtils.getSubject(),我們可以獲得當前正在執行的 Subject。Subject 是一個安全術語,它基本上的意思是 “當前正在執行的使用者的特定的安全檢視”。它並沒有被稱為”User”是因為”User”一詞通常和人類相關聯。在安全 界,術語”Subject”可以表示為人類,而且可是第三方程式,cron job,daemon account,或其他類似的東西。它僅僅 意味著“該事物目前正與軟體互動”。對於大多數的意圖和目的,你可以把 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()) {
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr","vespa");
            token.setRememberMe(true);
            
            try {
                currentUser.login(token);
            } catch (UnknownAccountException  e) {
                // TODO: handle exception
                log.info("there is no user with username of"+token.getPrincipal());
            }catch (IncorrectCredentialsException  e) {
                // TODO: handle exception
                log.info("Password for account"+token.getPrincipal()+"was incorrect");
            }catch (LockedAccountException  e) {
                // TODO: handle exception
                log.info("The account for username"+token.getPrincipal()+"is locked."+"Please contact your adminstrator to unlock it.");
            }
        }
        

比方說,

他們是是誰:

    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("winnebego: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();

 

以上程式碼完全版如下所示:

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.util.Factory;

public class Tutorial {


    

    private static Logger log = Logger.getLogger(Tutorial.class);
    
    public static void main(String[] args) {
    
        
        log.info("My First Apache Shiro Application");
        
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        
        SecurityManager securityManager = factory.getInstance();
        
        SecurityUtils.setSecurityManager(securityManager);
        
        org.apache.shiro.subject.Subject currentUser = SecurityUtils.getSubject();
        
        Session session = currentUser.getSession();
        
        session.setAttribute("someKey", "aValue");
        
        String value = (String) session.getAttribute("someKey");
        
        if(value.equals("aValue")) {
            log.info("Retrieved the correct value!["+value+"]");
        }
        
        if(!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr","vespa");
            token.setRememberMe(true);
            
            try {
                currentUser.login(token);
            } catch (UnknownAccountException  e) {
                // TODO: handle exception
                log.info("there is no user with username of"+token.getPrincipal());
            }catch (IncorrectCredentialsException  e) {
                // TODO: handle exception
                log.info("Password for account"+token.getPrincipal()+"was incorrect");
            }catch (LockedAccountException  e) {
                // TODO: handle exception
                log.info("The account for username"+token.getPrincipal()+"is locked."+"Please contact your adminstrator to unlock it.");
            }
        }
        
        log.info("User["+currentUser.getPrincipal()+"]"+"logged in successfully");
        
        //test a role
        
        if(currentUser.hasRole("schwartz")) {
            log.info("May the schwartz be with you!");
        }else {
            log.info("Hello,mere mortal");
        }
        
        if(currentUser.isPermitted("winnebego: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();
        System.exit(0);
        
    }
}

 

以上是完整的示例說明如下:

從建立工廠載入配置檔案shiro.init到建立安全管理器,到獲取當前使用者,到用sesion儲存使用者例項。

再到獲取使用者例項及其獲取使用者角色及其相應許可權

 


相關文章