【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:操作)