在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": "super@abc.com"
}

换一个用户,如果选择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,就可以拿到授权信息了:

Keycloak中授权的实现的更多相关文章

  1. 项目一:第十二天 1、常见权限控制方式 2、基于shiro提供url拦截方式验证权限 3、在realm中授权 5、总结验证权限方式(四种) 6、用户注销7、基于treegrid实现菜单展示

    1 课程计划 1. 常见权限控制方式 2. 基于shiro提供url拦截方式验证权限 3. 在realm中授权 4. 基于shiro提供注解方式验证权限 5. 总结验证权限方式(四种) 6. 用户注销 ...

  2. JAVAEE——BOS物流项目11:在realm中授权、shiro的方法注解权限控制、shiro的标签权限控制、总结shiro的权限控制方式、权限管理

    1 学习计划 1.在realm中进行授权 2.使用shiro的方法注解方式权限控制 n 在spring文件中配置开启shiro注解支持 n 在Action方法上使用注解 3.★使用shiro的标签进行 ...

  3. MySQL中授权(grant)和撤销授权(revoke

    MySQL 赋予用户权限命令的简单格式可概括为:   grant 权限 on 数据库对象 to 用户   一.grant 普通数据用户,查询.插入.更新.删除 数据库中所有表数据的权利 grant s ...

  4. 项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出

    1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法   Shiro框架内部整合好缓存管理器, ...

  5. mysql中授权其它电脑链接指令。

    grant all privileges on yourDatabaseName to 'user'@'databaseIPAddress' identified by 'password' with ...

  6. Xcode中授权普通成员

    问题: 在普通用户账户下使用系统的Xcode在编译通过时候会提示” Developer Tools Access“需控制另一进程,需要输入“Developer Tools”组用户名密码才能继续调试 解 ...

  7. 在wildfly中使用SAML协议连接keycloak

    目录 简介 OpenID Connect和SAML SAML的工作流程 在keycloak中使用SAML 准备wildfy和应用程序 简介 我们知道SSO的两个常用的协议分别是SAML和OpenID ...

  8. Shiro中的授权问题(二)

    上篇博客(Shiro中的授权问题 )我们介绍了Shiro中最最基本的授权问题,以及常见的权限字符的匹配问题.但是这里边还有许多细节需要我们继续介绍,本节我们就来看看Shiro中授权的一些细节问题. 验 ...

  9. 20190526 - CentOS 7 中 安装 MySQL 8 并授权 root 远程访问

    1. CentOS 7 中 安装 MySQL 8 CentOS 7 中内置 MariaDB 建议升级一下用,性能好很多.但如果一定要用 MySQL 8,就得自己装. 坦白的说,Oracle 升级 My ...

  10. asp.net core 3.x 授权中的概念

    前言 预计是通过三篇来将清楚asp.net core 3.x中的授权:1.基本概念介绍:2.asp.net core 3.x中授权的默认流程:3.扩展. 在完全没有概念的情况下无论是看官方文档还是源码 ...

随机推荐

  1. OPPO 自研大规模知识图谱及其在数智工程中的应用

    导读:OPPO 知识图谱是 OPPO 数智工程系统小布助手团队主导.多团队协作建设的自研大规模通用知识图谱,目前已达到数亿实体和数十亿三元组的规模,主要落地在小布助手知识问答.电商搜索等场景. 本文主 ...

  2. 3、dubbo核心用法

    https://dubbo.apache.org/zh/docs/v2.7/user/examples/preflight-check/ 1.启动时检查 在启动时检查依赖的服务是否可用 Dubbo 缺 ...

  3. 摆脱鼠标系列 - 打开微信(Alt+V) - 打开双核浏览器(Alt+S) - HotkeyP

    摆脱鼠标系列 - 打开微信(Alt+V) - 打开双核浏览器(Alt+S) - HotkeyP 新定义了两个快捷键 这两个比较常用

  4. WPF之x命名空间

    目录 x命名空间内容 x命名空间的Attribute x:Class x:ClassModifier x:Name x:FieldModifier x:Key x:Shared x命名空间的标记扩展 ...

  5. Rust 标准库 Trait 指南

    部分内容来自 Rust 2021 年期刊 内容目录 引言 Trait 基础 自动 Trait 泛型 Trait 格式化 Trait 操作符 Trait 转换 Trait 错误处理 迭代器 Trait ...

  6. 前端 nodejs 命令行自动调用编译 inno setup 的.iss文件

    项目中需要把前端代码用 electronjs 打包成 windows 安装包 使用的是开源的 inno setup 制作安装包 官网 虽然 ElectronJS 也有 electron-builder ...

  7. enum class 用法

    enum的主要缺点 1.类型不明确 首先,无法指定数据类型,导致我们无法明确枚举类型所占的内存大小.这种麻烦在结构体当中尤为突出,特别是当我们需要内存对齐和填充处理的时候. #include < ...

  8. 实时3D渲染它是如何工作的?可以在哪些行业应用?

    随着新兴技术--3D渲染的发展,交互应用的质量有了极大的提高.用实时三维渲染软件创建的沉浸式数字体验,几乎与现实没有区别了.随着技术的逐步改进,在价格较低的个人工作站上渲染3D图像变得更加容易,设计师 ...

  9. 00-【K210】API资料、电气接线图、PCB文件

    K210的接口说明文档 API接口文档: 链接:https://pan.baidu.com/s/1mlzYRJYQIeHSEMysp_v4cg?pwd=pjmv 提取码:pjmv 2.原理图.PCB文 ...

  10. 你是怎么处理vue项目中的错误的?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.错误类型 任何一个框架,对于错误的处理都是一种必备的能力 在Vue 中,则是定义了一套对应的错误处理规则给到使用者,且在源代码级别,对 ...