• Shiro学习之权限认证


    权限认证也就是访问控制,即在应用中控制谁能访问哪些资源.
    在权限认证中,最核心的是三个要素是:权限,角色和用户.
    权限,即操作资源的权力,比如访问某个页面,以及对某个模块的数据的添加,修改,删除,查看的权利(CRUD).
    角色,是权限的集合,一个角色可以包含多种权限
    用户,在shiro中代表访问系统的用户,即subject


    授权

    • 编程式授权,基于角色和权限的访问控制
    • 注解授权,jsp标签授权

    1.基于角色的访问控制
    配置shiro_role.ini文件

    [users]
    yyt=123,role1,role2
    jack=1234,role1
    
    • 1
    • 2
    • 3

    规则即:“用户名=密码,角色1,角色2”,如果需要在应用中判断用户是否有相应角色,就需要在相应的Realm中返回角色信息,也就是说Shiro不负责维护用户-角色信息,需要应用提供,Shiro只是提供相应的接口方便验证,后续会介绍如何动态的获取用户角色。

    首先我将重复的代码封装成一个方法,传入配置文件的名字,用户名,密码

    package com.kingsky;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    
    public class ShiroUtil {
        public static Subject login(String configPath, String userName,
                String passWord) {
            // 读取配置文件,初始化SecurityManager工厂
            Factory factory = new IniSecurityManagerFactory(
                    "classpath:"+configPath);
    
            // 获取到SecurityManager实例
            SecurityManager securityManager = factory.getInstance();
    
            // 把SecurityManager绑定到SecurityUtils中
    
            SecurityUtils.setSecurityManager(securityManager);
            // 得到当前用户
            Subject subject = SecurityUtils.getSubject();
    
            // 创建Token令牌,用户名/密码
            UsernamePasswordToken passwordToken = new UsernamePasswordToken(userName,
                    passWord);
            // 验证登录 会抛出异常
            try {
                subject.login(passwordToken);
                System.out.println("身份验证成功!!!");
            } catch (AuthenticationException e) {
                e.printStackTrace();
                System.out.println("身份验证失败!!!!");
            }
            return subject;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在测试类中进行测试,我没有使用junit进行测试,我是直接使用main方法测试
    1.1测试subject.hasRole(String roleName) 返回值是boolean

    public class TestRole {
        public static void main(String[] args) {
            Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
            //Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
            System.out.println(subject.hasRole("role2")?"有role2这个角色":"没有role2这个角色");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    控制台的输出是:有role2这个角色,
    如果是换成了jack,控制台输出的是:没有role2这个角色

    1.2测试subject.hasRoles(List roles) 返回值是boolean[]

    Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    //Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
    boolean[] results=subject.hasRoles(Arrays.asList("role1","role2"));
    for (boolean b : results) {
        System.out.println(b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    用户是yyt的时候,控制台输出的是:true,true,代表的是yyt拥有role1,role2这个角色
    用户是jack的时候,控制台出去的是:true,false,代表的是jack用户role1这个角色,但是没有role2这个角色

    1.3测试subject.hasAllRoles(List roles) 返回值是boolean

    Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    //Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
    System.out.println(subject.hasAllRoles(Arrays.asList("role1","role2"))?"有role2,role1这个角色":"role1,role2这个角色不全有");
    
    • 1
    • 2
    • 3

    用户是yyt的时候,控制台输出的是:有role2,role1这个角色
    用户是jack的时候,控制台出去的是:role1,role2这个角色不全有

    1.4测试subject.checkRole(String roleName) 没有返回值,假如验证失败,则会报错:
    org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role2]

    //Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
    subject.checkRole("role2");
    
    • 1
    • 2
    • 3

    1.5测试subject.checkRoles(String… roleIdentifiers) 可以传入多个角色名称,假如验证失败,则会报错:
    org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role2]

    Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    //Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
    subject.checkRoles("role2","role1");
    
    • 1
    • 2
    • 3

    1.6测试subject.checkRoles(String… roleIdentifiers) 可以传入多个角色名称,假如验证失败,则会报错:
    org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role2]

    Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    //Subject subject=ShiroUtil.login("shiro_role.ini", "jack", "1234");
    subject.checkRoles(Arrays.asList("role1","role2"));
    
    • 1
    • 2
    • 3

    2.基于权限的控制
    配置文件内容如下:shiro-permission.ini

    [users]
    yyt=123,role1,role2
    jack=1234,role1
    [roles]
    role1=user:create,user:update  
    role2=user:create,user:delete
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.1测试subject.isPermitted(String name) 返回boolean

    package com.kingsky;
    
    import org.apache.shiro.subject.Subject;
    
    public class TestPermission {
        public static void main(String[] args) {
            // Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
            Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
            boolean result= subject.isPermitted("user:create");
            System.out.println(result?"有user:create这个权限":"没有user:create这个权限");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    控制台输出:有user:create这个权限,假如权限名称改为:user:delete则输出的没有这个权限

    2.2测试subject.isPermittedAll(String… names) 返回boolean,代表是全有或者不全有这些权限

    // Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
    boolean result=subject.isPermittedAll("user:create","user:delete");
    System.out.println(result?"有user:create,update这些权限":"这些user:create,update权限不全有");
    
    • 1
    • 2
    • 3
    • 4

    控制台输出:有user:create,update这些权限
    假如修改权限:user:delete,则会返回fase

    2.3测试subject.isPermitted(String… names) 返回boolean[],对应的权限是不是有

    // Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
    boolean results[]=subject.isPermitted("user:create","user:delete");
    for (boolean b : results) {
        System.out.println(b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    控制台输出:true(代表user:create有权限),false(代表user:delete没有权限)

    2.4测试subject.checkPermission(String name);没有返回值,但是验证不成功则会报错:
    org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]

    // Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
    subject.checkPermission("user:delete");
    
    • 1
    • 2
    • 3

    2.5测试subject.checkPermissions(Stirng… names);没有返回值,但是验证不成功则会报错:
    org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]

    // Subject subject=ShiroUtil.login("shiro_role.ini", "yyt", "123");
    Subject subject = ShiroUtil.login("shiro-permission.ini", "jack","1234");
    subject.checkPermissions("user:create","user:update");
    
    • 1
    • 2
    • 3

    3.注解授权,jsp标签授权
    在JSP页面通过相应的标签完成:

      
      
      
    
    • 1
    • 2
    • 3

    4、Shiro对权限字符串缺失部分的处理
    如“user:view”等价于“user:view:”;而“organization”等价于“organization:”或者“organization::”。可以这么理解,这种方式实现了前缀匹配。
    另外如“user:”可以匹配如“user:delete”、“user:delete”可以匹配如“user:delete:1”、“user::1”可以匹配如“user:view:1”、“user”可以匹配“user:view”或“user:view:1”等。即_可以匹配所有,不加_可以进行前缀匹配;但是如“:view”不能匹配“system:user:view”,需要使用“:_:view”,即后缀匹配必须指定前缀(多个冒号就需要多个_来匹配)。

  • 相关阅读:
    体验不尽,进化不止,看视频云技术六大创新
    JAVAWEB_实验三 Servlet 相关技术
    Future
    Java#数据结构----1
    cuda编程学习——运行错误检测(四)
    CSRF攻击
    TeleVis:基于NLP的新冠新闻舆情可视化项目
    一起用Go做一个小游戏(上)
    GateWay网关
    一起Talk Android吧(第四百一十九回:让时钟走起来)
  • 原文地址:https://blog.csdn.net/m0_67401746/article/details/126496316