<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
為了解決專案當中的許可權管理問題,我們一般會選擇引入spring security或者shiro框架來幫助我們更好地更快地構建許可權管理體系。
首先第一步,我們需要給當前專案引入對應的依賴包。與spring boot整合一般首選starter包。
<!-- shiro許可權管理框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.9.1</version> </dependency>
無論是spring security還是shiro,兩者都是基於servlet的Filter過濾器機制實現的許可權管理。所以第一步設定我們就需要把對應的Filter給加入進來。
@Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 設定securityManager,負責許可權驗證的核心事務處理。 shiroFilterFactoryBean.setSecurityManager(securityManager()); // 設定過濾器鏈 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // anon表示該url不需要經過許可權驗證 filterChainDefinitionMap.put("/static/**", "anon"); // logout表示使用者登出功能的過濾器;呼叫指定的url會讓已經登陸的使用者退出 filterChainDefinitionMap.put("/logout", "logout"); // authc過濾器表示對應的url都需要許可權驗證才能存取 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); // 設定使用者登陸的url。呼叫該介面需要傳username和password欄位。 shiroFilterFactoryBean.setLoginUrl("/login"); // 登陸成功自動跳轉頁面 shiroFilterFactoryBean.setSuccessUrl("/index"); return shiroFilterFactoryBean; }
看上面程式碼,我們就可以分析出,需要把這些Filter過濾器建立出來,除了設定一些需要攔截的url之外,我們還要建立一個非常核心的securityManager,這個才是許可權驗證過程處理的核心。
@Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm()); return securityManager; }
別看securityManager裡面我只設定了Realm,其實securityManager就像一個大領導,壓根不幹活兒,有啥活都派給底下的小弟去幹。
我們來看看securityManager底下到底有哪些小弟;
後續的部落格中會逐一解析這些小弟的作用,今天就先把如何簡單整合shiro講完。
下面我們應該要給出如何判斷使用者登陸和鑑定使用者許可權了:
@Bean public UserRealm userRealm() { UserRealm userRealm = new UserRealm(); userRealm.setCredentialsMatcher(credentialsMatcher()); return userRealm; }
因為Realm需要查詢使用者的密碼已經改使用者對應的角色和許可權,所以我們自定義了自己的Realm。
通過繼承AuthorizingRealm:
package com.example.awesomespring.security; import com.example.awesomespring.bo.AccountInfo; import com.example.awesomespring.service.AccountService; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import javax.annotation.Resource; public class UserRealm extends AuthorizingRealm { @Resource private AccountService accountService; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // 從authenticationToken中獲取使用者提交的username String accountName = (String) authenticationToken.getPrincipal(); // 通過username查詢到對應的使用者資訊 AccountInfo accountInfo = accountService.findByAccount(accountName); if (accountInfo == null) { return null; } // 取出查詢到的使用者密碼 String password = accountInfo.getPassword(); // 取出使用者密碼加密需要用到的鹽值 String salt = accountInfo.getSalt(); // 把查詢出來的使用者資訊、密碼、加密鹽值、Realm名稱包裝進SimpleAuthenticationInfo返回 return new SimpleAuthenticationInfo(accountInfo, password, ByteSource.Util.bytes(salt), getName()); } // 這個方法是在使用者登陸成功後,呼叫需要許可權才能存取的介面時才來鑑定許可權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { // 拿到已經登陸的使用者資訊 AccountInfo accountInfo = (AccountInfo) principalCollection.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // 下面的角色和許可權需要從資料庫中查詢 // 設定角色 authorizationInfo.addRole("User"); // 設定許可權 authorizationInfo.addStringPermission("User:read"); // 返回角色和許可權 return authorizationInfo; } }
到這裡,我們可以看出,Realm就是用來幫助使用者登陸,並且在使用者存取需要許可權的介面時,查詢出使用者的角色和許可權,交給決策器來決定使用者是否登陸成功,鑑權是否通過。
這是一個不容易被注意的點,使用預設的設定時只會簡單的比較輸入的密碼和資料庫查出來的密碼是否一致,這顯然是不符合要求的,因為我們資料庫裡面的密碼是已經加密好了的。
另一個就是我們在建立使用者的時候也是需要使用到同樣的密碼加密手段,所以我們有必要把密碼加密給拎出來處理一下,做一個自定義的加密。
@Bean public CredentialsMatcher credentialsMatcher() { return new PasswordHashedCredentialsMatcher("MD5"); } package com.example.awesomespring.security; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.util.ByteSource; /** * @author zouwei * @className PasswordHashedCredentialsMatcher * @date: 2022/7/31 下午3:43 * @description: */ public class PasswordHashedCredentialsMatcher extends HashedCredentialsMatcher { public PasswordHashedCredentialsMatcher(String hashAlgorithmName) { super(hashAlgorithmName); setHashIterations(2); } public String encryptedPassword(String passwordString, String salt) { return hashProvidedCredentials(passwordString, ByteSource.Util.bytes(salt), getHashIterations()).toHex(); } }
其實我們就是繼承了HashedCredentialsMatcher,在它的基礎上提高了直接針對密碼加密的功能。這樣既能滿足shiro的登陸驗證,又能拿出來用到建立使用者的時候加密使用。
為了驗證我們的設定是否成功,我們需要寫幾個測試介面:
package com.example.awesomespring.controller; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") @Slf4j public class UserController { @GetMapping("/{id}") @RequiresPermissions("User:info") String getUserInfo(@PathVariable String id) { log.info("獲取使用者資訊開始"); log.info("請求引數 id:{}", id); log.info("獲取使用者資訊結束"); return "getUserInfo"; } @GetMapping("/hello") String hello() { return "hello world!"; } @GetMapping("/read") @RequiresPermissions("User:read") String read() { return "read"; } }
上面的幾個介面,我們如果直接存取的話,在瀏覽器中,會被重定向到"/login"頁面,因為我們目前沒有這個頁面,所以一旦重定向這個url,說明使用者沒有登陸。
其次我們通過呼叫post請求"/login",提交username和password成功登陸後,頁面會重定向到"/index"頁面,目前我們也是沒有這個頁面的,不過從響應體中可以看到響應碼是302。
當我們在使用者登陸成功後,再存取"/user/read"是能正常存取,並返回結果"read";如果存取"/user/123456"是不行的,頁面會直接報500錯誤。
通過上述測試,我們已經初步完成了shiro的整合
到此這篇關於springboot整合shiro許可權管理簡單實現的文章就介紹到這了,更多相關springboot 整合shiro內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45