https://blog.csdn.net/sco5282/article/details/134016549
前面已經學習了Shiro快速入門和快取 。現在假定實際業務中需要完成以下功能:
1. 包含頁面登入和首頁。
2. 登入時需要連線資料庫,完成登入認證和授權。
3. 登入時,密碼需要加密。
4. 登入和授權資訊能夠快取。
5. 授權演示兩種模式,基於角色授權和基於資源授權。
前提條件
因為這裡主要學習shiro,所以與shiro不相干的步驟和準備,儘量簡單表示。
1. 新建SpringBoot的Web專案,並新建頁面index.html(主頁,對應路由ip:介面/index)和login.html(登入頁面,對應路由ip:介面/login)。
2. mysql資料庫包含使用者、角色以及授權的表格(如下圖)。這些表格的方法已在SpringBoot結合(Mybatis或Mybatisplus)形成基礎的查詢方法,我們演示的時候只要呼叫以上方法即可。
引入依賴
這裡我們需要引用需要的shiro和redis依賴項。
1 <dependency> 2 <groupId>org.apache.shiro</groupId> 3 <artifactId>shiro-spring</artifactId> 4 <version>1.13.0</version> 5 </dependency> 6 <!-- Redis 快取--> 7 <dependency> 8 <groupId>org.springframework.boot</groupId> 9 <artifactId>spring-boot-starter-data-redis</artifactId> 10 <version>2.5.15</version> 11 </dependency> 12 <dependency> 13 <groupId>org.springframework.data</groupId> 14 <artifactId>spring-data-redis</artifactId> 15 <version>2.5.12</version> 16 </dependency>
新增Shiro配置類
根據已學過的知識,新增配置類ShiroConfiguratin。
1 @Configuration 2 public class ShiroConfiguratin { 3 @Autowired 4 private RedisTemplate redisTemplate; 5 6 // 1.建立 shiroFilter,負責攔截所有請求 7 @Bean 8 public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ 9 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 10 //給filter設定安全管理器 11 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); 12 //配置系統受限資源 13 //配置系統公共資源 14 Map<String,String> map = new HashMap<>(); 15 // authc 請求這個資源需要認證和授權 16 map.put("/index", "authc"); 17 //預設認證介面路徑 18 shiroFilterFactoryBean.setLoginUrl("/login"); 19 shiroFilterFactoryBean.setFilterChainDefinitionMap(map); 20 return shiroFilterFactoryBean; 21 } 22 23 //2.建立安全管理器 24 @Bean 25 public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){ 26 DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); 27 //給安全管理器設定 28 defaultWebSecurityManager.setRealm(realm); 29 return defaultWebSecurityManager; 30 } 31 32 /** 33 * 3.建立自定義realm 34 * @return 35 */ 36 @Bean 37 public Realm getRealm(){ 38 SysUserRealm sysUserRealm = new SysUserRealm(); 39 // 設定快取管理器 40 sysUserRealm.setCacheManager(new RedisCacheManage(redisTemplate)); // 自定義Redis資料庫快取方法 41 // 開啟全域性快取 42 sysUserRealm.setCachingEnabled(true); 43 // 開啟認證快取並指定快取名稱 44 sysUserRealm.setAuthenticationCachingEnabled(true); 45 sysUserRealm.setAuthenticationCacheName("authenicationCache"); 46 // 開啟快取授權並指定快取名稱 47 sysUserRealm.setAuthorizationCachingEnabled(true); 48 sysUserRealm.setAuthorizationCacheName("authenicationCache"); 49 return sysUserRealm; 50 } 51 }
這裡的配置類完成以下功能。
- 完成攔截請求(登入index頁面前,需要經過認證和授權認證和授權頁面(login))
- 建立安全管理(新增域管理器)
- 設定自定義域,完成快取的設定(使用Redis快取,詳見:https://www.cnblogs.com/luyj00436/p/18446712)。
根據之前學到的知識,自定義域完成了認證和授權 SysUserRealm 。
1 public class SysUserRealm extends AuthorizingRealm { 2 @Autowired 3 private SysUserMapper sysUserMapper; // 使用者查詢 4 /** 5 * 授權 6 * @param principals the primary identifying principals of the AuthorizationInfo that should be retrieved. 7 * @return 8 */ 9 @Override 10 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 11 // 從系統返回的身份資訊集合中獲取主身份資訊(使用者名稱) 12 String primaryPrincipal = (String) principals.getPrimaryPrincipal(); 13 // TODO 根據使用者名稱獲取當前使用者的角色資訊,以及許可權資訊 14 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); 15 // 將資料庫中查詢到的角色資訊賦值給許可權物件 16 simpleAuthorizationInfo.addRole("admin"); 17 simpleAuthorizationInfo.addRole("user"); 18 // 將資料庫中查詢許可權資訊賦值給許可權物件 19 simpleAuthorizationInfo.addStringPermission("user:*:01"); 20 simpleAuthorizationInfo.addStringPermission("product:create"); 21 return simpleAuthorizationInfo; 22 } 23 24 /** 25 * 認證 26 * @param token the authentication token containing the user's principal and credentials. 27 * @return 28 * @throws AuthenticationException 29 */ 30 @Override 31 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 32 // 在token中獲取使用者名稱 33 String principal = (String) token.getPrincipal(); // 獲取使用者名稱 34 // 根據獲取到的使用者名稱查詢資料(這裡用id代替) 35 SysUser resUser = sysUserMapper.selectById(1); 36 if(principal.equals(resUser.getUsername())){ 37 // 引數說明:使用者|密碼|當前realm的名字 38 return new SimpleAuthenticationInfo(principal,resUser.getPassword(), this.getName() ); 39 } 40 return null; 41 } 42 }