1. 程式人生 > >【shiro】許可權框架——基礎篇

【shiro】許可權框架——基礎篇

shiro是什麼
Apache Shiro是一個強大且易用的Java安全框架,有身份驗證、授權、密碼學和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程式,從最小的移動應用程式到最大的網路和企業應用程式。
shiro的作用
在這裡插入圖片描述
Shiro 開發團隊稱為“應用程式的四大基石” ——身份驗證,授權,會話管理和加密作為其目標。

Authentication(身份認證) :
有時也簡稱為“登入”,這是一個證明使用者是他們所說的他們是誰的行為。

Authorization(授權):
訪問控制的過程,也就是絕對“誰”去訪問“什麼”許可權。
 Session Management:管理使用者特定的會話,即使在非 Web 或 EJB 應用程式。
 Cryptography:通過使用加密演算法保持資料安全同時易於使用。
也提供了額外的功能來支援和加強在不同環境下所關注的方面,尤其是以下這些:
 Web Support: Shiro 的 web 支援的 API 能夠輕鬆地幫助保護 Web 應用程式。
 Caching:快取是 Apache Shiro 中的第一層公民,來確保安全操作快速而又高效。
 Concurrency: Apache Shiro 利用它的併發特性來支援多執行緒應用程式。
 Testing:測試支援的存在來幫助你編寫單元測試和整合測試,並確保你的能夠如預期的一樣安全。
 “Run As”:一個允許使用者假設為另一個使用者身份(如果允許)的功能,有時候在管理指令碼很有用。
 “Remember Me”:在會話中記住使用者的身份,所以他們只需要在強制時候登入。

架構:
shiro外部來看
從外部來看Shiro,即從應用程式角度(使用者)來如何使用shiro來完成工作(認證、授權等)。
在這裡插入圖片描述
在這裡插入圖片描述
Shiro內部看
即shiro內部夾走
在這裡插入圖片描述
在這裡插入圖片描述
匯入所需的包
在這裡插入圖片描述
拷貝資源
在這裡插入圖片描述
resources下面兩個配置檔案
log4j.properties
shiro.ini
java下面一個java檔案
Quickstart.java
在這裡插入圖片描述
測試:

public class Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

    	//通過一個配置了realms,users,roles,permissions的ini的配置檔案快速建立一個SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        //為了程式能偶正常執行,需要設定securityManager
        SecurityUtils.setSecurityManager(securityManager);

        //獲取當前使用者
        Subject currentUser = SecurityUtils.getSubject();

        //1 會話操作
        Session session = currentUser.getSession();//獲取session
        session.setAttribute("someKey", "aValue");//在session中設定值
        String value = (String) session.getAttribute("someKey");//從session中獲取值
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
            //return;
        }

        //2 身份認證(登入)
        //如果沒有登入
        if (!currentUser.isAuthenticated()) {
        	//把前臺傳入的使用者名稱和密碼建立一個UsernamePasswordToken
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            try {
            	//通過currentUser呼叫login傳入UsernamePasswordToken執行登入操作,如果不正確就會丟擲對應錯誤
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
            	//使用者不存在
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
            	//密碼不正確
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
            	//賬號被鎖定
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            //其他異常-AuthenticationException是上面一樣的父類
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //3 許可權
        //判斷當前使用者是否擁有該角色
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //測試許可權 lightsaber:*
        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.");
        }

        //a (very powerful) Instance Level permission:
        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!");
        }

        //all done - log out!
        currentUser.logout();

        System.exit(0);
    }
}

總結
通過SecurityManger獲取Suject
通過Subject來做事情:
獲取Session-存值和獲取值 Suject.getSession session.setAttribute session.getAttribute
認證(登入):
判斷是否登入Suject.isAuthenticated
如果沒有登入,通過使用者名稱和密碼建立UsernamePasswordToken
呼叫suject.login(UsernamePasswordToken)來進行登入判斷
授權
判斷是否具有某個角色subject .hasRole
判斷是否有許可權subject .isPrermited(resource:操作)