首页 > 其他分享 >Keycloak中授权的实现

Keycloak中授权的实现

时间:2024-04-13 16:35:35浏览次数:22  
标签:角色 实现 用户 点击 API weather 授权 Keycloak

在Keycloak中实现授权,首先需要了解与授权相关的一些概念。授权,简单地说就是某个(些)用户或者某个(些)用户组Policy),是否具有对某个资源Resource)具有某种操作Scope)的权限Permission)。所以,授权是一种权限管理,它建立在认证的基础上:用户首先要完成认证(Authentication),才能谈授权(Authorization)。在讨论认证与授权的文章或论坛里,往往用Authn代表认证(Authentication),而用Authz代表授权(Authorization)。

Keycloak中的授权模型

在上面这段描述中,我已经将几个重要的概念用黑体字标注了。或许会有这样的疑问:用户/用户组不应该是User/Group吗?在谈授权的时候,至少也应该是角色(Role)吧,比如我们熟悉的基于角色的访问控制(RBAC),里面就是角色,怎么会是策略(Policy)呢?在回答这个问题前,还是先看一下Keycloak中的授权模型:

这个模型中,包含了几个重要的概念:

  1. 资源(Resource):资源是应用程序中能够被访问的对象。假设有个有关天气预报的API,它的URL是http://localhost:5678/WeatherForecast,那么,在这台资源服务器上,URI /WeatherForecast就是一个资源的地址,它表示一个跟天气预报相关的API端点资源
  2. 操作(Scope):其实Scope并不翻译为“操作”,这里我使用“操作”来表示Scope,是因为在授权的场景中,Scope就是定义针对资源的一些“操作”。比如:对于上面的天气预报API资源,我们可以有获取资源的操作,也可以有更新资源的操作(比如,让气象员根据其它科学数据来调整某地的天气预报)。于是,在定义Scope的时候,可以用“weatherforecast.read”、“weatherforecast.update”这样的名字来命名
  3. 对于某个资源,它可以声明自己所需要的操作,例如,在RESTful API中,/WeatherForecast这个API可以有读取(read/HTTP GET)的操作,也可以有更新(update/HTTP PATCH)的操作,那么,就可以在这个API资源上声明weatherforecast.read和weatherforecast.update这两个Scope
  4. 一个用户组(Group)可以包含多个子组,一个组下可以有多个用户(User),一个用户又可以属于多个用户组。对于一个用户或者一个组而言,它可以扮演多种角色(Role),而一个角色又可以被赋予多个用户或者多个用户组,这些都是耳熟能详的RBAC授权的基本概念,就不多说明了
  5. 策略(Policy)可以理解为满足某种条件的资源访问者(可以是用户或用户组),所以,Policy定义的是条件:角色就是一种条件,表示“被赋予某种角色”的条件。基于角色的策略实现的访问控制,就是RBAC。当然条件不仅仅只有角色,用户满足某个条件也可以成为一种策略,比如要求某个用户年龄大于18岁。除此之外,策略是可以被聚合的,聚合策略的投票结果(允许还是拒绝),取决于被聚合的策略以及投票的方式(是所有被聚合策略都允许,结果才被允许,还是只要有一个投票为“允许”,整个聚合策略的结果就是“允许”),比如要求用户是年龄大于18岁(User Policy)的系统管理员(Role Policy)。上图中只简单列了几个继承于Policy的子类用以示意,Keycloak所支持的策略类型不止这些
  6. 权限(Permission)是资源(Resource)或者操作(Scope)与策略(Policy)之间的关联关系。在Keycloak中,权限分为两种:基于资源的权限和基于操作的权限。表达的语义是:符合某些策略的访问者对指定的资源或者操作可以访问

理解了这些概念后,在Keycloak中实现授权并不困难。

演练:在Keycloak中实现授权

还是以Weather API为例,设置这样的业务场景:

  1. 服务供应商(Service Provider)发布/WeatherForecast API供外部访问
  2. 在企业应用(Client)里有三个用户:super,daxnet,nobody
  3. 在企业应用里有两个用户组:administrators,users
  4. 在企业应用里定义了两个用户角色:administrator,regular user
  5. super用户同时属于users和administrators组,daxnet属于users组,nobody部署于任何组
  6. administrators组被赋予了administrator角色,users组被赋予了regular user角色
  7. 对于/WeatherForecast API,它支持两种操作:GET /WeatherForecast,用以返回天气预报数据;PATCH /WeatherForecast,用以调整天气预报数据
  8. 拥有administrator角色的用户/组,具有PATCH操作的权限;拥有regular user角色但没有administrator角色的用户/组,具有GET操作的权限;没有任何角色的用户,就没有访问/WeatherForecast API的权限

这个业务场景也可以用下面的图来表述:

首先,在Keycloak中新建一个名为aspnetcoreauthz的Realm,在这个Realm下,新建三个User,分别是super,daxnet和nobody;然后新建两个Group:administrators和users,将super用户放到administrators组和users组里,并将daxnet用户放入users组里。

然后,新建一个名为weatherapiclient的Client,在weatherapiclient的页面里,点击Roles选项卡,创建两个名为administrator和regular user的角色,然后回到Groups里,选中administrators组,在Role mapping中,将administrator角色赋予该组:

用同样的方法,将regular user角色赋予users组。

现在进入Authorization选项卡,点击Scopes选项卡,然后点击Create authorization scope按钮:

在Create authorization scope页面中,Name字段输入weather.read,用同样的方法,新建另一个Scope,名称为weather.update。然后点击Resources选项卡,并点击Create resource按钮,创建API resource:

在Create resource页面,新建名为weather-api的资源,填入如下字段,然后点击Save按钮保存:

回到Authorization标签页,点击Policies标签页,点击Create client policy按钮,在弹出的对话框中,选择Role,表示需要创建一个基于角色的策略。在Create role policy页面,新建一个名为require-admin-policy的策略,在Roles部分,点击Add roles按钮,选择weatherapiclient下的administrator角色,然后点击Save按钮保存:

用同样的方法创建require-registered-user策略,并将regular user作为角色加入。接下来开始创建权限实体(Permission)。在Authorization选项卡里,点击Permission选项卡,然后点击Create permission,然后选择Create scope-based permission。在Create scope-based permission页面,创建一个名为weather-view-permission的Permission,Authorization scopes选择weather.read,Policies选择require-registered-user,这里的语义已经很明白了:执行weather.read操作,需要require-registered-user策略,也就是要读取天气预报信息,就需要已注册用户。点击Save按钮保存即可。

用同样的方法创建另一个名为weather-modify-permission的Permission,Authorization scopes为weather.update,Policies为require-admin-policy。

接下来,就可以测试权限的设置是否正确了。仍然在Authorization选项卡下,点击Evaluate选项卡,在Identity Information部分,Users里选择super:

然后点击Evaluate按钮,之后就可以看到,weather-modify-permission和weeather-view-permission均投票为Permit,表示该用户具有两者权限:

如果点击Show authorization data,则在弹出的Authorization data对话框中,可以看到token里已经包含了授权信息(authorization Claim):

{
  "exp": 1712996185,
  "iat": 1712995885,
  "jti": "4f1178f2-5e8b-41e4-b726-da9120d77baa",
  "aud": "weatherapiclient",
  "sub": "44bbfc3a-16a0-499a-aae9-a2aa36219d33",
  "typ": "Bearer",
  "azp": "weatherapiclient",
  "session_state": "2b228dd4-38c8-4002-bc11-b35ecd109a63",
  "acr": "1",
  "allowed-origins": [
    "/*"
  ],
  "realm_access": {
    "roles": [
      "default-roles-aspnetcoreauthz",
      "offline_access",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "weatherapiclient": {
      "roles": [
        "administrator",
        "regular user"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "authorization": {
    "permissions": [
      {
        "scopes": [
          "weather.update",
          "weather.read"
        ],
        "rsid": "f6fd1d6f-3bfd-44a1-a6fb-a1fb49769ac9",
        "rsname": "weather-api"
      }
    ]
  },
  "scope": "email profile",
  "sid": "2b228dd4-38c8-4002-bc11-b35ecd109a63",
  "email_verified": false,
  "name": "Admin User",
  "groups": [
    "/administrators",
    "/users"
  ],
  "preferred_username": "super",
  "given_name": "Admin",
  "family_name": "User",
  "email": "[email protected]"
}

换一个用户,如果选择daxnet,可以看到,weather-view-permission为Permit,而weather-modify-permission为Deny:

再将用户换为nobody测试一下,发现两个Permission的结果都为Deny:

通过token API端点请求授权信息

要使用OpenID Connect的token API端点获得某个用户的授权信息,需要首先得到Bearer token:

然后,使用这个Bearer token,再次调用token API,注意此时的grant_type为 urn:ietf:params:oauth:grant-type:uma-ticket,audience为Client ID,即weatherapiclient:

在jwt.io中解码第二步生成的这个access_token,就可以拿到授权信息了:

标签:角色,实现,用户,点击,API,weather,授权,Keycloak
From: https://www.cnblogs.com/daxnet/p/18132246

相关文章

  • 原型设计工具比较及实现
    原型设计工具比较及实践目录一,原型设计工具比较1.墨刀2.Axure3.Mockplus二,原型设计1.主题名称2.功能3.界面设计考虑因素4.切换界面一,原型设计工具比较1.墨刀使用领域​墨刀是界面原型设计工具,用于创建应用程序、网站和其他软件的交互原型。......
  • 原型设计工具比较及实现
    1、对比分析墨刀、Axure、Mockplus等原型设计工具的各自的适用领域及优缺点1.墨刀优点:用户界面:墨刀的用户界面非常直观和易用,适合新手和非技术背景的设计师。协作功能:支持多用户实时在线编辑和项目管理,便于团队协作。资源丰富:内置了大量的模板和元件库,可以快速拖拽来......
  • 基于PyTorch框架的多层全连接神经网络实现MNIST手写数字分类
    基于PyTorch框架的多层全连接神经网络实现MNIST手写数字分类简单的三层全连接神经网络导入了PyTorch相关的库,定义了一个名为SimpleNet的类,继承自nn.Module,这个神经网络有三个全连接层,分别是layer1、layer2和layer3。在初始化函数__init__中,指定了输入维度in_dim、两个隐藏层的神......
  • aspcore+jenkins+iis+window实现自动化部署
    一、准备工作1、Windowsserver2106操作系统2、Git 链接:https://pan.baidu.com/s/1s_3kKe5GWxJx1twggjk6Qg提取码:mayx3、IIS10确保已安装4、.netcoresdk6 https://download.visualstudio.microsoft.com/download/pr/9cac8293-8......
  • 原型设计工具比较及实现
    以下是对墨刀、Axure和Mockplus的对比分析:墨刀适用领域:快速原型设计:墨刀提供了简单易用的界面,适合快速原型设计和迭代。团队协作:墨刀支持多人实时协作,团队成员可以即时查看和编辑原型。云端存储:墨刀的云端存储功能使得原型可以轻松地分享和访问。优点:易于上手:用户界面简......
  • Ubuntu18.04安装opensips一次过,实现sip语音视频通话
    安装方式apt命令安装,不建议使用此方式想要在ubuntu18.04(建议使用18.04,不出错)上通过apt命令安装的可以借鉴一下这篇文章,但是这篇文章中博主有错误并未解决,下面是解决方式执行下列命令,使用opensipsdbctl创建数据库的时候会报错opensipsdbctlcreate#错误信息为ERROR:......
  • mybatis怎么实现insert into多个数据-oracle数据库
    第一种<insertid="insertBatch"> INSERTALL <foreachcollection="list"item="user"separator=""close="SELECT*FROMdual"index="index"> INTOLY_TEST(id,name,age)VALUES(#{user......
  • 2-74. 利用 AStar 实现 NPC 的移动
    运行游戏看看人物能否到网格中点修改NPCMovement修改Settings修改AStarTest调试修复Bug一开始人物未显示原因是currentScene没有进行赋值,可能currentScene是通过StartScene变量进行赋值的,但是我并没有找到赋值的地方,所以我暂时先写死这个变量算了......
  • 一步一步实现 .NET 8 部署到 Docker
    一、前言本文仅针对操作系统为 CentOS8 的环境下部署方法进行讲述。如有需要,后续将在其他文章中进行其他系统下的部署方式讲解。二、准备工作       1、是的犯得上大师傅士大夫是的犯得上发射点大师傅但是犯得上撒旦发射点犯得上犯得上发生发生发射点发 ......
  • 一步一步实现 .NET 8 部署到 Docker
    一、前言本文仅针对操作系统为CentOS8的环境下部署方法进行讲述。如有需要,后续将在其他文章中进行其他系统下的部署方式讲解。二、准备工作确保服务器已安装docker。可以通过命令docker-v进行检查,如出现下图结果则表示已安装。代码准备在代码项目名称上右键,依次......