zoukankan      html  css  js  c++  java
  • 5、Shiro实现授权

    授权

    授权概述

    授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、 角色(Role)。

    关键对象介绍

    • 主体

      主体,即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。

    • 资源

      在应用中用户可以访问的任何东西,比如访问JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。

    • 权限

      安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如:访问用户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD式权限控制)打印文档等等。

    • 角色

      角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。

    授权流程

    相关方法说明:

    //判断是否有角色 
    subject.hasRole(""); 
    //分别判断用户是否具有List中每个内容 
    subject.hashRoles(List);
    //返回boolean,要求参数中所有角色用户都需要具有
    subject.hasAllRoles(Collection); 
    //判断是否具有权限.
    subject.isPermitted("");
    

    shiro.ini方式实现授权

    1、配置shiro.ini

    # 配置用户
    [users]
    zhangsan=123456,role1
    lisi=123456,role3
    
    # 配置角色
    [roles]
    role1=user:view,user:create,user:delete,user:update
    role2=user:view
    role3=user:view,user:create
    

    权限标识符号规则:资源:操作:实例,中间使用半角:分隔。

    user:create:01 :表示对用户资源的01实例进行create操作。

    user:create:表示对用户资源进行create操作,相当于user:create:*,对所有用户资源实例进行create操作。

    user:*:01 :表示对用户资源实例01进行所有操作。

    2、测试用户是否有当前角色和权限

    package com.coydone.test;
    
    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;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class AuthUserTeat {
    
        public static void main(String[] args) {
            //1、接收用户名和密码
            String username = "zhangsan";
            String password = "123456";
    
            //2、把用户名和密码封装
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    
            //3、创建安全管理器的工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    
            //4、从Factory中得到安全管理器
            SecurityManager securityManager = factory.getInstance();
    
            //5、把securityManager和Subject绑定到当前线程
            SecurityUtils.setSecurityManager(securityManager);
    
            //6、从SecurityUtils中得到subject
            Subject subject = SecurityUtils.getSubject();
    
            //7、去认证
            try {
                subject.login(token);
                System.out.println("认证通过");
            } catch (AuthenticationException e) {
                System.out.println("用户名或密码不正确");
            }
            /*
            catch (IncorrectCredentialsException e) {
                System.out.println("密码不正确");
            } catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
            }
             */
    
            //8、查看认证状态
            System.out.println("认证状态:"+subject.isAuthenticated());
    
            //查看用户是否有role1的角色
            System.out.println("用户是否有role1的角色:"+subject.hasRole("role1"));
            //查看用户是否有role1、role2的角色
            List<String> list = new ArrayList<>();
            list.add("role1");
            list.add("role2");
            boolean[] isRoles = subject.hasRoles(list);
            for (boolean  isRole: isRoles) {
                System.out.println(isRole);
            }
            //查看用户是否有user:view的权限
            System.out.println(subject.isPermitted("user:view"));
    
            //9、退出
            subject.logout();
            System.out.println("认证状态:"+subject.isAuthenticated());
        }
    }
    
    

    注意,从以上的代码中可以看出我们的用户,密码,角色,权限都是在shrio.ini里面配置的,但是实际开发中我们的所有数据都是从数据库里面来的,如何实现呢,那就要使用数据和+自定义realm。

    自定义Realm实现授权

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //创建授权对象
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //添加角色
        info.addRole("role1");
        info.addRole("role2");
        //添加权限
        info.addStringPermission("user:view");
        info.addStringPermission("user:create");
        info.addStringPermission("user:delete");
        info.addStringPermission("user:update");
        return info;
    }
    

    总结

    Realm中有两个方法:doGetAuthenticationInfo()用作认证,doGetAuthorizationInfo()用作授权。当hasRoles()、hasRole()、isPermised()、isPermisedAll()方法被调用时,doGetAuthorizationInfo()方法就被执行一次。所以在开发中去查询用户权限的代码应该写在认证里面,因为认证只会执行一次。

    在授权中可以用principals.getPrimaryPrincipal()方法获取认证中的SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password,this.getName());中的第一个参数。这个参数可以是任意类型。

    所以一般在认证方法里面查询用户权限和角色之后使用一个ActiveUser类把用户、角色、权限封装传递给授权的方法。

    coydone的博客
  • 相关阅读:
    微信 token ticket jsapi_ticket access_token 获取 getAccessToken get_jsapi_ticket方法
    PHP 日志 记录 函数 支持 数组 对象 新浪 sae 环境 去掉 空格 换行 格式化 输出 数组转字符串
    原生 原始 PHP连接MySQL 代码 参考mysqli pdo
    PHP 数字金额转换成中文大写金额的函数 数字转中文
    使用PHPMailer发送带附件并支持HTML内容的邮件
    设置输出编码格式 header 重定向 执行时间 set_time_limit 错误 报告 级别 error_reporting
    html5 bootstrap pannel table 协议 公告 声明 文书 模板
    指向指针的指针
    二级指针
    c语言:当指针成为参数后
  • 原文地址:https://www.cnblogs.com/coydone/p/13779971.html
Copyright © 2011-2022 走看看