在java开发中常用到两个权限安全框架,一是spring security,二是shiro。两者区别是spring security是针对spring和spring boot项目的权限安全框架,而shiro则对环境无特别要求,可用于多种开发环境,并且相对简单,入门更加容易。本次主要就是分享shiro框架下对项目权限实现细粒度的划分,以及权限认证等基本操作。

shiro权限框架有三大核心内容,一是Subject(主体)指的是当前用户或者权限,二是SecurityManager(安全管理器)管理认证和授权的容器,三是Realm(域对象)实现具体的认证和授权逻辑流程。shiro架构图如下:

SpringBoot集成shiro权限安全框架_安全管理

shiro认证授权流程图如下:

SpringBoot集成shiro权限安全框架_shiro_02

想要访问系统资源时,必须通过身份认证才能进行访问,若没认证成功则继续认证,若认证成功则权限流程介入,检测该主体是否有某些权限,若没有则无法访问,若有则继续访问权限下的该资源,这样就实现了细粒度的权限安全管理。

如果对前面讲述得概念不是很理解,那接下来就用一个简单案例来展示具体的操作和流程。首先由于是SpringBoot项目,所以需要导入相关的依赖,导入如下依赖即可:

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>

<!--         springboot和mybatis的整合-->
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>1.1.1</version>
                </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.16</version>
        </dependency>

<!--        thymeleaf依赖-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>


        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>


        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-quartz</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!-- <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.4.0</version> </dependency> -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

其中主要包含的就是shiro相关的坐标依赖和thymeleaf依赖及thymeleaf整合shiro的依赖。创建一个配置类用来存放shiro相关的配置,该配置类中主要用来创建三个东西,Realm域对象,SecurityManager安全管理器,ShiroFilterFactoryBean过滤器工厂。

SpringBoot集成shiro权限安全框架_权限细粒度_03

由于域对象需要自定义,就如上图创建的UserRealm类一样,但创建好后只是一个普通类要让它成为域对象必须继承AuthorizingRealm类并实现其中的授权和认证方法。然后在配置类中方法返回该对象:

SpringBoot集成shiro权限安全框架_安全管理_04

接下来是安全管理器,由于安全管理器中需要管理域对象,所以要把自定义的域对象传入,并放回DefaultWebSecurityManager安全管理器对象。

SpringBoot集成shiro权限安全框架_shiro_05

最后配置ShiroFilterFactoryBean过滤器工厂,过滤器工厂中需要安全管理器对象,所以也要将安全管理器对象传入其对应的方法中,然后在设置过滤拦截条件以及没有认证成功后返回的界面。

SpringBoot集成shiro权限安全框架_安全管理_06

配置完毕后,该实现具体的认证授权流程了,在controller层编写简单的登录方法,该方法中就涉及到认证和授权了,第一步是获取Subject对象(这里指的就是当前登录的用户),将前台输入的用户名和密码传入token令牌中进行管理,然后将令牌传入subject.login(token)执行登录方法,该方法会自动先调用自定义域对象中的认证方法,认证方法认证成功再调用授权方法。

SpringBoot集成shiro权限安全框架_权限细粒度_07

认证过程连接数据库根据token令牌里存储的用户名信息对数据库中的用户名进行认证匹配,如果查询到的结果为null则证明认证失败,返回null抛出异常,反之则继续认证密码,但由于密码容易泄露所以由shiro框架直接接管自行匹配,编程人员无需关心。

SpringBoot集成shiro权限安全框架_权限细粒度_08

认证成功后就是授权了,在授权方法中获取认证方法返回的查询到的当前用户对象

SpringBoot集成shiro权限安全框架_shiro_09

,根据用户id查询用户权限码集合,再创建授权对象,添加权限信息,由于授权对象添加授权信息的参数是hashset集合,所以还需要创建一个hashset来存放查询出的权限码,然后把权限对象返回给前端页面进行判断显示。

SpringBoot集成shiro权限安全框架_shiro_10

这里有个注意点是必须前端上先绑定shiro权限判定标签后,才能自动自行授权方法。

最后进行测试,当前数据库中有两个用户如下:

SpringBoot集成shiro权限安全框架_安全管理_11

root用户的权限只有add添加权限,而lxj用户只有update权限,预期结果是root用户如果成功登录上系统后只能看到add,lxj用户则只能看到update。

SpringBoot集成shiro权限安全框架_权限细粒度_12

若输入与数据库不匹配的用户名和密码会显示用户名或密码错误。

root用户登录成功:

SpringBoot集成shiro权限安全框架_shiro_13

lxj用户登录成功:

SpringBoot集成shiro权限安全框架_权限细粒度_14

这样shiro权限安全框架就实现完毕,权限的细粒度划分也就此实现。