0、寫在前面的話
很久沒寫博客了,誒,好多時候偷懶直接就抓網上的資料丟筆記裏了,也就沒有本身提煉,偷懶偷懶。而後最近參加了一個網絡課程,要交做業的那種,爲了能方便看下其餘同窗的做業,就寫了個爬蟲把做業爬下來,進而想到若是之後還有相似這種狀況,我須要一個很是輕量化的架子,可是權限依然是必需要用到的,不然寫個接口人人均可以調用那還得了,可是我僅僅須要一我的或者一兩我的的權限配置就能夠了,因此像以前我寫過一個基於RBAC的架子甚至都仍是有點嫌重(並且那個架子尚未前端頁面,哈,真是懶),因此想到了用shiro.ini。
Shiro在不少quick start的demo中都用到了shiro.ini配置文件,用來配置帳戶密碼、角色、權限,它也寫好了現成的方法能夠讀取文件直接給你配置好SecurityManager,因此省去了本身在代碼裏定義Realm、配置過濾器啥的,可是實際上你們在作Web時基本都不用這玩意兒,由於自定義其實也不是很費時,我也就是蛋疼吧,既然都鼓搗了,那就仍是鼓搗到有個雛形。
一、踩坑記錄
Shiro很久沒碰了,又從新回顧了下大概幾個概念:
- SecurityManager是核心,全部和安全有關的操做都要和它交互,並且管理者全部Subject
- Realm用來驗證用戶,能夠理解爲DataSource安全數據源
- 權限攔截是經過過濾器,配置好urls和shiro默認過濾器的映射關係,shiro將會對requestUrl進行過濾鏈的匹配,並選擇過濾器進行處理
[users]
zhang=123,admin
wang=123,admin,vip
[roles]
admin=user:delete
[urls]
/static/**=anon
/login=anon
/authc/admin/user/delete=perms["user:delete"]
/authc/admin/user/create=perms["user:create"]
/authc/admin/**=roles[admin]
/authc/home=roles[admin,vip]
/authc/**=authc
shiro.ini中的 [main] 用不上了,由於這部分的配置和SpringBoot結合就在類中進行配置,這裏就不須要了,只須要 [users]、[roles]、[urls],其中[users] 和 [roles] 用來建立 Realm,[urls] 用來配置過濾器
踩坑:
- urls過濾匹配中,是按順序執行匹配到的第一個過濾器,因此要注意順序,如上圖若是把 /authc/** 放在開頭,後面的基本就匹配不到了
- urls中對於諸如perms或roles的描述,是「且」不是「或」
- 好比 roles[admin,vip] 表示同時擁有admin和vip角色的帳戶,而不是擁有admin或vip角色的帳戶
- * 匹配零個或多個字符 ** 匹配零個或多個路徑
@Configuration
public class ShiroConfig {
@Bean
public DefaultWebSecurityManager securityManager() {
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
DefaultSecurityManager defaultSecurityManager = (DefaultSecurityManager) securityManager;
DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();
webSecurityManager.setRealms(defaultSecurityManager.getRealms()); //important
SecurityUtils.setSecurityManager(securityManager);
return webSecurityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Ini ini = new Ini();
ini.loadFromPath("classpath:shiro.ini");
Map<String, String> map = new LinkedHashMap<>();
ini.getSection("urls").entrySet().forEach(url -> {
map.put(url.getKey(), url.getValue());
});
//過濾鏈
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
return shiroFilterFactoryBean;
}
}
踩坑
- SecurityManager是必定要有的,可是Shiro中讀取shiro返回的是 DefaultSecurityManager,由於是Web應用咱們須要的是 DefaultWebSecurityManager,因此把 DefaultSecurityManager的Realms 提出來給 DefaultWebSecurityManager
- 過濾鏈仍是得注入在Bean中的 FilterChainDefinitionMap 屬性纔是,因此對於shiro.ini的配置,使用 Ini 類的 loadFromPath 來讀取,再放置到map中
...
<packaging>war</packaging>
...
...
<!-- jsp支持 start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!-- jsp支持 end -->
...
#application.properties
spring.mvc.view.prefix=/WEB-INF/pages/
spring.mvc.view.suffix=.jsp