shiro與ssm整合使用
- 2019 年 10 月 5 日
- 筆記
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_37933685/article/details/82561258
個人博客:https://suveng.github.io/blog/
shiro
簡介
Apache Shiro是一個強大而靈活的開源安全框架,它能夠乾淨利落地處理身份認證,授權,企業會話管理和加密
- 驗證用戶
- 對用戶執行訪問控制,如: 判斷用戶是否擁有角色admin。判斷用戶是否擁有訪問的權限
- 在任何環境下使用 Session API。例如CS程序。
- 可以使用多個用戶數據源。例如一個是oracle用戶庫,另外一個是mysql用戶庫。
- 單點登錄(SSO)功能。
- 「Remember Me」服務 ,類似購物車的功能,shiro官方建議開啟
組件

Shiro的4大部分——身份驗證,授權,會話管理和加密
- Authentication:身份驗證,簡稱「登錄」。
- Authorization:授權,給用戶分配角色或 者權限資源
- Session Management:用戶session管理器,可以讓CS程序也使用session來控制權限
- Cryptography:把JDK中複雜的密碼加密方式進行封裝。

流程

概念
- Subject Subject 是與程序進行交互的對象,可以是人也可以是服務或者其他,通常就理解為用戶。 所有Subject 實例都必須綁定到一個SecurityManager上。我們與一個 Subject 交互,運行時shiro會自動轉化為與 SecurityManager交互的特定 subject的交互。
- SecurityManager SecurityManager 是 Shiro的核心,初始化時協調各個模塊運行。然而,一旦 SecurityManager協調完畢,SecurityManager 會被單獨留下,且我們只需要去操作Subject即可,無需操作SecurityManager 。 但是我們得知道,當我們正與一個 Subject 進行交互時,實質上是 SecurityManager在處理 Subject 安全操作。
- Realms Realms在 Shiro中作為應用程序和安全數據之間的「橋樑」或「連接器」。他獲取安全數據來判斷subject是否能夠登錄,subject擁有什麼權限。他有點類似DAO。在配置realms時,需要至少一個realm。而且Shiro提供了一些常用的 Realms來連接數據源,如LDAP數據源的JndiLdapRealm,JDBC數據源的JdbcRealm,ini文件數據源的IniRealm,properties文件數據源的PropertiesRealm,等等。我們也可以插入自己的 Realm實現來代表自定義的數據源。 像其他組件一樣,Realms也是由SecurityManager控制
實體圖

- Subject(org.apache.shiro.subject.Subject): 簡稱用戶
- SecurityManager(org.apache.shiro.mgt.SecurityManager) 如上所述,SecurityManager是shiro的核心,協調shiro的各個組件
- Authenticator(org.apache.shiro.authc.Authenticator): 登錄控制
註:Authentication Strategy (org.apache.shiro.authc.pam.AuthenticationStrategy) 如果存在多個realm,則接口AuthenticationStrategy會確定什麼樣算是登錄成功(例如,如果一個Realm成功,而其他的均失敗,是否登錄成功?)。
- Authorizer(org.apache.shiro.authz.Authorizer) : 決定subject能擁有什麼樣角色或者權限。
- SessionManager(org.apache.shiro.session.SessionManager) : 創建和管理用戶session。通過設置這個管理器,shiro可以在任何環境下使用session。
- CacheManager(org.apahce.shiro.cache.CacheManager) : 緩存管理器,可以減少不必要的後台訪問。提高應用效率,增加用戶體驗。
- Cryptography(org.apache.shiro.crypto.*) : Shiro的api大幅度簡化java api中繁瑣的密碼加密。
- Realms(org.apache.shiro.realm.Realm) : 程序與安全數據的橋樑
配置
涉及的jar
Jar包名稱 |
版本 |
---|---|
核心包shiro-core |
1.2.0 |
Web相關包shiro-web |
1.2.0 |
緩存包shiro-ehcache |
1.2.0 |
與spring整合包shiro-spring |
1.2.0 |
Ehcache緩存核心包ehcache-core |
2.5.3 |
Shiro自身日誌包slf4j-jdk14 |
1.6.4 |
與spring整合
- 在web.xml中配置shiro的過濾器
1536491038635
- 在Spring的applicationContext.xml中添加shiro配置

securityManager:這個屬性是必須的。 loginUrl :沒有登錄的用戶請求需要登錄的頁面時自動跳轉到登錄頁面,不是必須的屬性,不輸入地址的話會自動尋找項目web項目的根目錄下的」/login.jsp」頁面。 successUrl :登錄成功默認跳轉頁面,不配置則跳轉至」/」。如果登陸前點擊的一個需要登錄的頁面,則在登錄自動跳轉到那個需要登錄的頁面。不跳轉到此。 unauthorizedUrl :沒有權限默認跳轉的頁面。 過濾器簡稱 對應的java類 anon org.apache.shiro.web.filter.authc.AnonymousFilter authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter port org.apache.shiro.web.filter.authz.PortFilter rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter ssl org.apache.shiro.web.filter.authz.SslFilter user org.apache.shiro.web.filter.authc.UserFilter logout org.apache.shiro.web.filter.authc.LogoutFilter
- anon:例子/admins/**=anon 沒有參數,表示可以匿名使用。
- authc:例如/admins/user/**=authc表示需要認證(登錄)才能使用,沒有參數
- roles:例子/admins/user/=roles[admin],參數可以寫多個,多個時必須加上引號,並且參數之間用逗號分割,當有多個參數時,例如admins/user/=roles[「admin,guest」],每個參數通過才算通過,相當於hasAllRoles()方法。
- perms:例子/admins/user/**=perms[user:add:*],參數可以寫多個,多個時必須加上引號,並且參數之間用逗號分割,例如 /admins/user/**=perms["user:add:*,user:modify:*"] 當有多個參數時必須每個參數都通過才通過,想當於isPermitedAll()方法。
- rest:例子/admins/user/=rest[user],根據請求的方法,相當於/admins/user/=perms[user:method] ,其中method為post,get,delete等。
- port:例子/admins/user/**=port[8081],當請求的url的端口不是8081是跳轉到
- schemal://serverName:8081?queryString,其中schmal是協議http或https等,serverName是你訪問的host,8081是url配置里port的端口,queryString 是你訪問的url里的?後面的參數。
- authcBasic:例如/admins/user/**=authcBasic沒有參數表示httpBasic認證
- ssl:例子/admins/user/**=ssl沒有參數,表示安全的url請求,協議為https
- user:例如/admins/user/**=user沒有參數表示必須存在用戶,當登入操作時不做檢查
註:anon,authcBasic,auchc,user是認證過濾器, perms,roles,ssl,rest,port是授權過濾器
- 在applicationContext.xml中添加securityManagerper配置

- 配置bosRealm(自定義)


- 配置shiro註解模式

@RequiresAuthentication:驗證用戶是否登錄,等同於方法subject.isAuthenticated() 結果為true時。 @ RequiresUser:驗證用戶是否被記憶,user有兩種含義:一種是成功登錄的(subject.isAuthenticated() 結果為true);另外一種是被記憶的( subject.isRemembered()結果為true)。 @ RequiresGuest:驗證是否是一個guest的請求,與@ RequiresUser完全相反。換言之,RequiresUser == ! RequiresGuest 。此時subject.getPrincipal() 結果為null. @ RequiresRoles:例如: @RequiresRoles("aRoleName"); void someMethod(); 如果subject中有aRoleName角色才可以訪問方法someMethod。如果沒有這個權限則會拋出異常AuthorizationException。 @RequiresPermissions:例如: @RequiresPermissions( {"file:read", "write:aFile.txt"} ) void someMethod(); 要求subject中必須同時含有file:read和write:aFile.txt的權限才能執行方法someMethod()。否則拋出異常AuthorizationException。
- 自定義realm <!–自定義的myRealm 繼承自AuthorizingRealm,也可以選擇shiro提供的 –> <bean id="myRealm" class="com.yada.shiro.MyReam"></bean> //這是授權方法 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName = (String) getAvailablePrincipal(principals); //TODO 通過用戶名獲得用戶的所有資源,並把資源存入info中 ……………………. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setStringPermissions(set集合); info.setRoles(set集合); info.setObjectPermissions(set集合); return info; } //這是認證方法 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //token中儲存着輸入的用戶名和密碼 UsernamePasswordToken upToken = (UsernamePasswordToken)token; //獲得用戶名與密碼 String username = upToken.getUsername(); String password = String.valueOf(upToken.getPassword()); //TODO 與數據庫中用戶名和密碼進行比對。比對成功則返回info,比對失敗則拋出對應信息的異常AuthenticationException ………………….. SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password .toCharArray(),getName()); return info; }
- 自定義登錄 //創建用戶名和密碼的令牌 UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassWord()); //記錄該令牌,如果不記錄則類似購物車功能不能使用。 token.setRememberMe(true); //subject理解成權限對象。類似user Subject subject = SecurityUtils.getSubject(); try { subject.login(token); } catch (UnknownAccountException ex) {//用戶名沒有找到。 } catch (IncorrectCredentialsException ex) {//用戶名密碼不匹配。 }catch (AuthenticationException e) {//其他的登錄錯誤 } //驗證是否成功登錄的方法 if (subject.isAuthenticated()) { }
- 自定義登出 Subject subject = SecurityUtils.getSubject(); subject.logout();
- 基於編碼的角色授權實現 Subject currentUser = SecurityUtils.getSubject(); if (currentUser.hasRole("administrator")) { //擁有角色administrator } else { //沒有角色處理 }
- 斷言方式控制 Subject currentUser = SecurityUtils.getSubject(); //如果沒有角色admin,則會拋出異常,someMethod()也不會被執行 currentUser.checkRole(「admin"); someMethod();
- 在JSP上的TAG實現 標籤名稱 標籤條件(均是顯示標籤內容) shiro:authenticated 登錄之後 shiro:notAuthenticated 不在登錄狀態時 shiro:guest 用戶在沒有RememberMe時 shiro:user 用戶在RememberMe時 <shiro:hasAnyRoles name=「abc,123」 > 在有abc或者123角色時 <shiro:hasRole name=「abc」> 擁有角色abc <shiro:lacksRole name=「abc」> 沒有角色abc <shiro:hasPermission name=「abc」> 擁有權限資源abc <shiro:lacksPermission name=「abc」> 沒有abc權限資源 shiro:principal 默認顯示用戶名稱