shiro(授权)

1、 shiro中的授权
1.1、 授权

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

1.2、 关键对象

授权可简单理解为who 对 what 进行 how操作:

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

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

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

1.3、 授权流程

在这里插入图片描述

1.4、 授权方式

基于角色的访问控制

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

if(subject.hasRole("admin")){
    //操作什么资源
}

​ 基于资源的访问控制

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

if(subject.isPermission("user:create:*")){      //资源类型
    //对所有用户具有创建权限
}
if(subject.isPermission("user:create:9527")){   //资源类型
    //对9527用户具有创建权限
}
1.5、 权限字符串

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

​ 例子

​ 用户创建权限 : user:create,或 user:create:*

​ 用户修改001权限 : user:create,或 user:update:001

​ 用户实例001的所有权限 :user:*:001

1.6、 shiro 中授权编程的实现方式
  1. 编程式
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole("admin")){
    //有权限
}else{
    //无权限
}
  1. 注解式
@RequiresRoles("admin")
public void hello(){
    //有权限
}

  1. 标签式
JSP/GSP 标签:在JSP/GSP  页面通过相应的标签完成:
<shiro:hasRole name="admin">
<!- 有权限->
</shiro:hasRole>
注意:thymeleaf 中使用shiro需要额外集成!
1.7、 开发授权
  1. 自定义realm
package com.tzm.shiro.realm;

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;

/***
 * 使用自定义realm
 */
public class CustomerMD5Realm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("===================");
        String  primaryPrincipal = (String) principals.getPrimaryPrincipal();
        System.out.println("身份信息:"+primaryPrincipal);
        //根据身份信息 用户名 获取当前用户的角色信息,以及权限信息 baobe  admin user
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRole("user");
        //将数据库中查询角色信息赋值给权限对象
        simpleAuthorizationInfo.addRole("admin");

        simpleAuthorizationInfo.addStringPermission("user:*:01");
        simpleAuthorizationInfo.addStringPermission("product:create:*");
        return  simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户信息
        String principal = (String) token.getPrincipal();
        //根据用户名查数据库
        if ("baobe".equals(principal)) {
            // 参数1: 数据库用户名
            //2:数据库md5+salt 之后的密码
            //3:注册时的随机数
            //4:realm 的名字
            return new SimpleAuthenticationInfo(principal,
                    "e343805db85797f023cdfd9ee31e4944",
                    ByteSource.Util.bytes("Xo**78ps"),
                    getName());
        }

        return null;
    }
}

  1. 使用自定义的ream
package com.tzm.shiro;
import com.tzm.shiro.realm.CustomerMD5Realm;
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.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import java.util.Arrays;

public class TestCustomerMD5RealmAuthenticator {
    public static void main(String[] args) {
        //创建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        CustomerMD5Realm realm = new CustomerMD5Realm();
        //设置realm 使用hash 凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //使用算法md5
        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("baobe", "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()){
            //基于角色权限控制
            System.out.println("subject.hasRole(\"admin\") = " + subject.hasRole("super"));
            //基于多角色权限控制
            System.out.println("subject.hasAllRoles(Arrays.asList(\"admin\",\"user\")) = " + subject.hasAllRoles(Arrays.asList("admin", "user")));

            //是否具有其中一个角色
            boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "user", "super"));
            for (boolean aBoolean : booleans) {
                System.out.println(aBoolean);
            }
            System.out.println("==============================");
            System.out.println("权限 " + subject.isPermitted("user:*:01"));
            System.out.println("权限 " + subject.isPermitted("product:create:01"));

            //分别具有哪些属性
            boolean[] permitted = subject.isPermitted("user:*:01", "order:*:01");
            for (boolean b : permitted) {
                System.out.println("  "+b);
            }
            //同时具有哪些权限
            boolean permittedAll = subject.isPermittedAll("user:*:01", "product:create:1");
            for (boolean b : permitted) {
                System.out.println("  "+b);
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.诗酒趁年华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值