• springboot+shiro+layuimini实现后台管理系统的权限控制(三)利用shiro实现对用户的授权


    用户成功登入我们系统之后,下一步就是要根据用户的角色给用户授予相应的权限。

    Shiro支持的权限控制范围很广,大到一个模块的权限,小到一个按钮的操作权限都可以通过shiro来进行控制。

    一、shiro基于权限的访问控制

    主要有三种调用方式:

    1、编码:

    1. Subject subject = SecurityUtils.getSubject();
    2. if(subject.hasRole(“admin”)) {
    3. //有权限
    4. } else {
    5. //无权限
    6. }

    2、注解:

    1. @RequiresRoles("admin")
    2. public void hello() {
    3. //有权限
    4. }

    3、标签:

    1. "admin">

    无论是哪一种访问控制调用方式,都会从主体(Subject)委托给SecurityManager最终委托给Realm下的doGetAuthorizationInfo()中来执行授权操作,并把授权结果返回到上层。

    二、shiro的授权方式

    shiro提供了两种授权方式,一种是基于角色的授权,即根据用户的角色来判定是否有相应的权限,另一种是基于权限字符串的授权,即根据事先约定好的权限字符串来控制权限。

    与认证类似,需要实例化一个授权对象:simpleAuthorizationInfo,将角色或权限字符串赋值给它。

    1、基于角色的授权:

    1.1、单个角色

    1. //添加角色信息给权限对象
    2. //单个角色
    3. simpleAuthorizationInfo.addRole("admin");

    1.2、多个角色

    1. //多个角色
    2. List roleList = new ArrayList<>();
    3. roleList.add("admin");
    4. roleList.add("user");
    5. simpleAuthorizationInfo.addRoles(roleList);
    1. Subject currentUser = SecurityUtils.getSubject();
    2. //1、基于角色权限控制
    3. System.out.println(currentUser.hasRole("admin"));
    4. //2、基于多角色权限控制
    5. System.out.println(currentUser.hasAllRoles(Arrays.asList("admin", "user")));

    同样执行这段代码,1.1 打印出来的结果应该是ture,false,而1.2打印出来的结果应该是true,true。

    2、基于权限字符串的授权:

    1. //添加权限字符串给权限对象
    2. simpleAuthorizationInfo.addStringPermission("user:create:01");
    3. simpleAuthorizationInfo.addStringPermission("user:update");
    1. Subject currentUser = SecurityUtils.getSubject();
    2. //1、基于权限字符串的访问控制 资源标识符:操作:资源类型
    3. System.out.println(currentUser.isPermitted("user:create:*"));
    4. //2、分别具有哪些权限
    5. boolean[] permitteds = currentUser.isPermitted("user:create", "user:update");
    6. for (boolean per : permitteds) {
    7. System.out.println(per);
    8. }

    shiro权限字符串的规则是:资源标识符:操作:实例,权限字符串也可以使用*,表示全部。shiro字符串通配符规则十分强大同时也很复杂,如果想要详细了解,可以去这里-字符串通配符权限这一段看看。

    这里可以简单理解为:"模块\角色:操作:具体实例",比如user:create:01的含义就是,该用户具有user模块\角色的创建权限,但只能操作实例名为01的资源(如编号为01的订单)。而"user:update"则代表拥有user下修改所有资源的权限。也可以写作"user:update:*"。

    三、代码实现

    1、前台通过shiro标签控制按钮权限:

    1. <shiro:hasPermission name="user:add:*">
    2. <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add">
    3. 添加 button>
    4. shiro:hasPermission>

    在顶层标签添加:xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"

    还有一点值得注意的是,如果想在html中使用shiro标签还需要在ShiroConfig中添加如下代码:

    1. @Bean
    2. public ShiroDialect getShiroDialect(){
    3. return new ShiroDialect();
    4. }

    关于在html中引入shiro标签,可以看看这篇博客:基于thymyleaf模板引擎下的html中引入shiro标签

    2、从数据库中读取权限信息并授权:

    1. /**
    2. * 授权
    3. */
    4. @Override
    5. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    6. System.out.println("进入授权流程:---->doGetAuthorizationInfo");
    7. SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
    8. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    9. List resourceList = sysResourceService.findPermissions(user.getRole());
    10. for(SysResource resource : resourceList){
    11. simpleAuthorizationInfo.addStringPermission(resource.getPermission());
    12. }
    13. return simpleAuthorizationInfo;
    14. }
    15. /**
    16. * 认证
    17. */
    18. @Override
    19. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    20. System.out.println("进入认证流程:---->doGetAuthenticationInfo");
    21. String userName = (String) token.getPrincipal();
    22. SysUser sysUser = sysUserService.findUserByName(userName);
    23. //用户不存在
    24. if (sysUser == null) {
    25. return null;
    26. }
    27. //验证密码,使用加盐md5进行加密
    28. SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(sysUser, sysUser.getPassword(), getName());
    29. authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(userName));
    30. return authenticationInfo;
    31. }

    因为我在登录认证的SimpleAuthenticationInfo中传入的是SysUser是一个对象,因此我在授权中可以通过 SysUser user = (SysUser) principalCollection.getPrimaryPrincipal(); 直接拿到这个对象。

    sys_user(用户表):

     sys_resource(资源权限表):

     sys_resource_role(资源-角色表):

     这是相关联的几张数据库表的信息,可以看到,这里是通过一张中间表sys_resource_role,将用户和资源关联了起来,用户名yuyan拥有添加的权限,而yuyan2则没有,反映在页面上,也就是yuyan这个用户可以看到添加这个按钮,而yuyan2则不行:

     

     ok,那么这样就完成了对按钮的授权操作了!

  • 相关阅读:
    python趣味编程-5分钟实现一个F1 赛车公路游戏(含源码、步骤讲解)
    Golang 中的 String、rune 和 byte
    产品经理要不要考PMP?进化你能力的阶梯!(附:新版考纲及教材)
    取代Webpack的打包工具Turbopack究竟有多快
    简单工厂模式(一)在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式
    博达:经营管理再升级,从选对CRM开始
    R语言logistic回归的细节解读
    C语言——全局变量和局部变量重名了会怎么样
    十六、代码校验(4)
    【毛毛讲书】【混合信号】如何更好地设计激励措施?
  • 原文地址:https://blog.csdn.net/superyu1992/article/details/126014248