Shiro学习笔记(四):Shiro中的授权

一、授权介绍

1、授权

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

对于授权可以理解为谁对哪些资源进行什么操作,授权中的关键对象如下:

  • 主体:主体需要访问系统中的资源
  • 资源:如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为g01的商品则称为资源实例,订单编号为o01的订单也为资源实例。
  • 权限/许可:规定了主体对资源的操作许可,如:用户查询权限、用户添加权限、某个类方法的调用权限、对编号为g01的商品的修改权限等,通过权限可知道主体对哪些资源具有哪些操作权限。

2、授权流程

3、授权方式

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

示例如下:

//基于角色的访问控制
if(subject.hasRole("admin")){
    //操作资源
}
//基于资源的角色控制
if(subject.isPermission("user:update:01")){
    //拥有对01用户的修改权限
}
if(subject.isPermission("user:update:*")){
    //拥有对所有用户的修改权限
}

4、权限字符串

权限字符串是以字符串的方式实现对授权规则的表示,其规则是:资源标识符:操作:资源实例标识符,意思是对哪个资源的哪个实例具有什么操作,:是资源/操作1/实例的分隔符,权限字符串也可以使用*作为通配符。示例如下:

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

5、shiro中授权编程实现方式

(1)编程式

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

(2)注解式

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

(3)标签式

<shiro:hasRole name="admin">
</shiro:hasRole>

二、Shiro实现授权示例

1、角色验证

方法说明如下:

方法名

说明

hasRole

是否具有某个角色

hasAllRole

是否具有所有角色

hasRoles

分别具有哪些角色

代码:

package org.example.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

import java.util.Arrays;

public class TestMD5 {
//    21232f297a57a5a743894a0e4a801fc3
//    a5599b5184c1aadc0877cd76cb93a969
//    578422679b493529e22c5495c8b3db3c
    public static void main(String[] args) {
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //注入realm
        UserMD5Realm realm = new UserMD5Realm();
        //设置realm使用hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        //设置散列次数
        credentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(credentialsMatcher);
        //设置Realm
        defaultSecurityManager.setRealm(realm);
        //将安装工具类中设置默认安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");
        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()){
            System.out.println(subject.hasRole("拥有的角色"));
            //hasRole判断是否具有某种角色
            System.out.println("hasRole方法");
            if(subject.hasRole("admin")){
                System.out.println("admin拥有管理员角色");
            }else{
                System.out.println("admin没有管理员角色");
            }
            //hasAllRoles判断是否同时具有这些角色
            System.out.println("hasAllRoles方法");
            if(subject.hasAllRoles(Arrays.asList("admin", "super", "users"))){
                System.out.println("admin拥有管理员、超级管理员和用户角色");
            }else{
                System.out.println("admin不同时具有这些角色");
            }
            //hasRoles是否具有其中一个角色
            System.out.println("hasRoles方法");
            boolean[] roles = subject.hasRoles(Arrays.asList("admin", "super", "users"));
            for(boolean b : roles){
                System.out.println(b);
            }
        }
    }
}


package org.example.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

public class UserMD5Realm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        //根据身份信息 用户名获取当前用户的角色信息和权限信息,这一块从数据库中读取。
        //本案例中,我们假设admin用户具有管理员权限和普通用户的角色
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRole("admin");
        simpleAuthorizationInfo.addRole("users");
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取身份信息
        String principal = (String) authenticationToken.getPrincipal();
        if("admin".equals(principal)){
            //这里的密码模拟是从数据库中读到的
            String password = "578422679b493529e22c5495c8b3db3c";
            return new SimpleAuthenticationInfo(principal, password, ByteSource.Util.bytes("vasdg"), this.getName());
        }
        return null;
    }
}

2、基于权限字符串的访问控制

方法说明如下:

方法名

说明

isPermitted

是否具有某个权限

isPermitted

是否具有其中部分角色,前一个方法的重载

isPermittedAll

是否具有所有角色

代码:

基于上述代码加入以下逻辑:

TestMD5的主方法

//具有某种权限
            System.out.println("是否具有对01用户的修改权限 : " + subject.isPermitted("user:update:01"));
            //分别具有哪些权限
            boolean[] permitted01 = subject.isPermitted("user:*:01", "order:update:01");
            for(boolean b : permitted01){
                System.out.println(b);
            }
            //同时具有哪些权限
            boolean permitted02 = subject.isPermittedAll("user:*:01", "order:update:01");
            System.out.println(permitted02);

UserMD5Realm的doGetAuthorizationInfo()方法:

        //基于权限字符串的访问控制
        simpleAuthorizationInfo.addStringPermission("user:*:01");
        simpleAuthorizationInfo.addStringPermission("product:create:01");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值