SpringBoot + Shiro + shiro.ini 的踩坑记录


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

SpringBoot 对 JSP 的支持并不友好,因此须要一些额外的配置,参考资料《 Spring Boot 添加 JSP 支持
相关文章
相关标签/搜索