Shiro 五 rbac权限模型理解,并用ini方式检查用户拥有角色

RBAC:基于角色的权限管理

简单理解为:谁扮演什么角色,被允许做什么操作;或者说谁拥有什么身份,能够有什么权限。

用户对象:user:当前操作用户

角色对象:role:表示权限操作许可权的集合

权限对象:permission:资源操作许可权

例如:张三(user)下载(permission)一个高清的电影(资源),需要VIP(role)权限。

张三------》普通用户----》授权----》VIP用户-----》下载电影

授权方式:

1.编程方式

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole("admin")){
    // 有权限
}else{
    // 没权限
}

2.注解方式:

通过在执行的java方法上放置相应的注解完成

@RequiresRoles("admin")
public void hello(){
    // 有权限
}

3.jsp标签的方式

在jsp页面通过相应的标签完成

<shiro:hasRole name="admin">
    <!- 有权限 显示,没权限则不显示->
</shiro:hasRole>

权限表达式定义

在ini文件中用户、角色、权限的配置规则是:“用户名=密码,角色1,角色2……”,首先根据用户名找角色,再根据角色找权限,角色是权限集合。

权限字符串的规则是:“资源标识符:操作;资源实例表示符”,意思是对那个资源的哪个实例具有什么操作,“:”是资源、操作、实例的分隔符,权限字符串也可以使用“*”通配符。

例子:

用户创建权限:user:create,或user:create:*

用户修改实例001权限:user:update:001

用户实例001的所有权限:user:*:001

一般而已,我们操作只需要关注前面两节;

资源:操作:*:*:所有资源的所有操作 

使用ini方式判断是否有角色

1.结构图

Shiro 五 rbac权限模型理解,并用ini方式检查用户拥有角色

2.pom文件

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.study</groupId>
  <artifactId>shiro</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>shiro</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>


    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.3</version>
    </dependency>

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.2</version>
    </dependency>

  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

3.配置文件shiro-permission.ini

[users]
zhangsan=666,role1,role2
lisi=666,role2

[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
#角色role2对资源user拥有create、delete权限
role2=user:create,user:delete
#角色role3对资源user拥有create
role2=user:create

4.加载配置文件,测试用户是否拥有角色

 @Test
    public void testLoginByRole() throws Exception{
        // 1.创建SecurityManager工厂对象,加载配置文件,创建
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
        // 2.通过工厂对象,创建Securitymanage对象
        SecurityManager securityManager = factory.getInstance();
        // 3.将securitymanage绑定到当前运行环境中,让系统随时随地的都可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        // 4:创建当前登录的主体,注意;此时主体没有经过认证
        Subject subject = SecurityUtils.getSubject();
        // 5:绑定主体登录的身份、凭证,即账号密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","666");
        try {
            // 6.主体登录
            subject.login(token);
            System.out.println("成功登录……" );
            // 进行授权操作的前提:用户必须通过认证
            // 判断当前用户是否拥有某个角色,true表示拥有,false表示没有
            if (subject.hasRole("role1")){
                System.out.println("拥有");
            }else {
                System.out.println("没有");
            }
            // 判断当前用户是否拥有一些角色,true表示全部拥有,false表示不全部拥有(有一个不拥有就是false)
            if (subject.hasAllRoles(Arrays.asList("role1","role2"))){
                System.out.println("全部拥有");
            }else {
                System.out.println("不全部拥有");
            }

            // 判断当前用户是否拥有一些角色,返回的是boolean类型的数组,trule表示拥有,false表示没有
            System.out.println(Arrays.toString(subject.hasRoles(Arrays.asList("role1","role2","role3"))));

            // 判断是否拥有某个角色,拥有该角色的时候没有返回值,没有该角色测时候回报错,org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role3]
            subject.checkRole("role1");
            // 判断是否拥有某个角色,有一个没有报错
            subject.checkRoles("role1","role2","role3");


        }catch (IncorrectCredentialsException incorrectCredentialsException){
            System.out.println("密码错误!");
        }catch (UnknownAccountException UnknownAccountException){
            System.out.println("用户名错误!");
        }
        // 7:判断是否登录成功
        System.out.println("验证是否登录1:" + subject.isAuthenticated());
        // 8:登出
        subject.logout();
        System.out.println("验证是否登录2:" + subject.isAuthenticated());
    }