【SpringBoot】Shiro(四)授权概念和伪代码实现

在这里插入图片描述

引言:Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架

授权简介

授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。


关键对象3W模型

授权可简单理解为who对what(which)进行How操作:

Who,即主体(Subject),主体需要访问系统中的资源。

What,即资源(Resource),如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型资源实例,比如商品信息为资源类型,类型为t01的商品为资源实例,编号为001的商品信息也属于资源实例。

How,权限/许可(Permission),规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可。


授权流程

在这里插入图片描述


两种授权方式RBAC

  • (1)基于角色的访问控制

    • RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制

      # 伪代码
      if(subject.hasRole("admin")){
         //操作什么资源
      }
      
  • (2)基于资源的访问控制

    • RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制

      # 伪代码
      if(subject.isPermission("user:update:01")){ //资源实例
        //对01用户进行修改
      }
      if(subject.isPermission("user:update:*")){  //资源类型
        //对01用户进行修改
      }
      

权限字符串

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

例子:

  • 用户创建权限:user:create,或user:create:*
  • 用户修改实例001的权限:user:update:001
  • 用户实例001的所有权限:user:*:001

Shiro授权的编程实现

  • 编程式

    Subject subject = SecurityUtils.getSubject();
    if(subject.hasRole(“admin”)) {
    	//有权限
    } else {
    	//无权限
    }
    
  • 注解式

    @RequiresRoles("admin")
    public void hello() {
    	//有权限
    }
    
  • 标签式 注意: Thymeleaf 中使用shiro需要额外集成!

    JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:
    <shiro:hasRole name="admin">
    	<!— 有权限—>
    </shiro:hasRole>
    

实现Demo

思路:

  • 创建一个身份信息对象simpleAuthorizationInfo
  • 将数据库中查询到角色信息赋值给权限对象
  • addRole添加身份角色信息——addRole
  • 将数据库中查询权限信息赋值给权限对象——addStringPermission

CustomerMd5Realm 返回域Realm

public class CustomerMd5Realm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取身份信息
        String primaryPrincipal = (String) principals.getPrimaryPrincipal();
        System.out.println("身份信息:"+primaryPrincipal);
        //根据身份信息 用户名 获取当前用户的角色信息,以及权限信息 xiaozhang admin user

        //创建一个身份信息对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //将数据库中查询到角色信息赋值给权限对象
        //addRole添加身份角色信息——addRole
        simpleAuthorizationInfo.addRole("admin");
        simpleAuthorizationInfo.addRole("user");


        //将数据库中查询权限信息赋值给权限对象——addStringPermission
        simpleAuthorizationInfo.addStringPermission("user:*:01");
        simpleAuthorizationInfo.addStringPermission("product:create");



        return simpleAuthorizationInfo;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取身份信息
        String principal = (String) token.getPrincipal();
        //根据用户名查询数据库
        if ("xiaozhang".equals(principal)){
            //e10adc3949ba59abbe56e057f20f883e是123456
            //4521de6bab32eb309f1d6b8756fc2984是123456加盐后的md5
            //fee9f57ca13bd0c77caa5f41184d052c是123456加盐后散列1024次的md5
            //参数一:数据库用户名、 参数二:数据库md5+salt之后的密码、 参数三:注册时的随机盐 参数四:realm的名字
            return new SimpleAuthenticationInfo(principal,
                    "fee9f57ca13bd0c77caa5f41184d052c",
                    ByteSource.Util.bytes("X07ps"),
                    this.getName());
        }
        return null;
    }
}

测试 TestCustomerMd5RealmAuthenticator

ublic class TestCustomerMd5RealmAuthenticator {
    public static void main(String[] args) {
        //创建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //注入realm
        CustomerMd5Realm realm = new CustomerMd5Realm();
        //创建realm使用的hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //设置凭证匹配器的算法
        credentialsMatcher.setHashAlgorithmName("md5");
        //设置凭证匹配器散列的次数
        credentialsMatcher.setHashIterations(1024);
        //将凭证匹配器注入到realm中
        realm.setCredentialsMatcher(credentialsMatcher);
        //将realm注入到安全管理器中
        defaultSecurityManager.setRealm(realm);

        //将安全管理器注入全局安全工具
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //通过全局安全工具获取subject
        Subject subject = SecurityUtils.getSubject();
        //创建认证令牌
        UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang","123456");

        try {
            subject.login(token);
            System.out.println("登录成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误");
        }

        //授权
        if (subject.isAuthenticated()){
            //基于角色权限控制
            //赋予了user和admin角色
            System.out.println(subject.hasRole("admin"));
            System.out.println(subject.hasRole("user"));
            //没有赋予superi角色
            System.out.println(subject.hasRole("super"));

            //基于多角色控制
            System.out.println(subject.hasAllRoles(Arrays.asList("admin","user")));

            //基于是否具有其中一个角色
            boolean [] booleans = subject.hasRoles(Arrays.asList("admin","super","user"));
            for (boolean aBoolean :  booleans){
                System.out.println(aBoolean);
            }

            //基于权限字符串访问控制 资源标识符:操作:资源类型
            //
            System.out.println("权限:"+subject.isPermitted("user:update:01"));
            System.out.println("权限:"+subject.isPermitted("product:create:02"));

            //分别具有哪些权限
            boolean [] permitted = subject.isPermitted("user:*:01","order:*:10");
            for (boolean b : permitted){
                System.out.println(b);
            }

            //同时具有哪些权限
            boolean perittedAll = subject.isPermittedAll("user:*:01","product:create:01");
            System.out.println(perittedAll);
        }

    }
}
//授权xiaozhang这个用户admin和user角色,不存在super角色
//授权user:*:01和product:create两个权限字符串

//根据以下判断代码,检索对应结果如下



===============================================

登录成功
身份信息:xiaozhang
true
身份信息:xiaozhang
true
身份信息:xiaozhang
false
身份信息:xiaozhang
身份信息:xiaozhang
true
身份信息:xiaozhang
身份信息:xiaozhang
身份信息:xiaozhang
true
false
true
身份信息:xiaozhang
权限:true
身份信息:xiaozhang
权限:true
身份信息:xiaozhang
身份信息:xiaozhang
true
false
身份信息:xiaozhang
身份信息:xiaozhang
true

===============================================


        if (subject.isAuthenticated()){
            //基于角色权限控制
            //赋予了user和admin角色
            System.out.println(subject.hasRole("admin"));
            System.out.println(subject.hasRole("user"));
            //没有赋予superi角色
            System.out.println(subject.hasRole("super"));

            //基于多角色控制
            System.out.println(subject.hasAllRoles(Arrays.asList("admin","user")));

            //基于是否具有其中一个角色
            boolean [] booleans = subject.hasRoles(Arrays.asList("admin","super","user"));
            for (boolean aBoolean :  booleans){
                System.out.println(aBoolean);
            }

            //基于权限字符串访问控制 资源标识符:操作:资源类型
            //
            System.out.println("权限:"+subject.isPermitted("user:update:01"));
            System.out.println("权限:"+subject.isPermitted("product:create:02"));

            //分别具有哪些权限
            boolean [] permitted = subject.isPermitted("user:*:01","order:*:10");
            for (boolean b : permitted){
                System.out.println(b);
            }

            //同时具有哪些权限
            boolean perittedAll = subject.isPermittedAll("user:*:01","product:create:01");
            System.out.println(perittedAll);
        }


—end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值