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的博客
  • 相关阅读:
    一个老菜鸟所理解的UX及产品流
    自学MVC看这里——全网最全ASP.NET MVC 教程汇总
    Windows10的革命之路-全新UWP开发平台
    七天学会ASP.NET MVC(七)——创建单页应用
    Windows10 会不会成为微软的新起点?
    Visual Studio 2015速递(4)——高级特性之移动开发
    Visual Studio 2015速递(3)——ASP.NET 新特性
    Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力)
    Visual Studio 2015速递(1)——C#6.0新特性怎么用
    Mac OS 环境下 安装 Asp.Net及使用Yeoman 创建Asp.Net 项目
  • 原文地址:https://www.cnblogs.com/coydone/p/13779971.html
Copyright © 2011-2022 走看看