完全透明度 - 我绝不是Keycloak,OAuth或OIDC专家,我所知道的大多来自阅读文档、书籍、好老YouTube和玩弄工具。
本文将由两部分组成:
- 我将尽力回答你们所有的问题
- 我将向您展示如何在Keycloak中玩弄策略/范围/权限,而无需部署单独的应用程序,以更好地理解本主题中的一些核心概念。请注意,这主要是为了让您们入门。我正在使用
Keycloak 8.0.0
。
第一部分
开始之前先介绍一些术语:
在Keycloak中,您可以创建两种类型的权限:
基于资源和
基于范围。
简单来说,对于
基于资源
的权限,您直接将其应用于您的资源。
对于
基于范围
的权限,您将其应用于您的范围或范围
和资源。
“在多个资源(帐户、交易等)之间使用一个“视图”范围并且重复使用它是最佳实践吗?还是应该创建“viewAccount”范围,“viewTransaction”范围等?”
范围表示受保护资源的一组权限。 在您的情况下,您有两个资源:
帐户
和
交易
,因此我会倾向于采取第二种方法。
从长远来看,将全局“视图”范围与所有资源(例如“账户”,“交易”,“客户”,“结算”等)相关联,使得授权难以管理和适应安全要求的变化。
以下是一些示例,您可以查看以了解设计感:
请注意 - 我并不是在说您不应该跨资源共享范围。事实上,“Keycloak”允许具有相同类型的资源进行此操作。例如,您可能需要“viewAccount”和“viewTransaction”范围来读取给定帐户下的交易(毕竟您可能需要访问帐户才能查看交易)。您的要求和标准将严重影响您的设计。
针对每种资源和范围的实际组合,通常做法是创建一条许可吗?
抱歉,我不完全理解这个问题,所以我会比较宽泛地回答。为了允许/拒绝访问某个
资源
,您需要:
- 定义您的策略
- 定义您的许可
- 将您的策略应用于您的许可
- 将您的许可关联到一个
范围
或资源
(或两者都有)
才能生效进行策略执行。请参见
授权过程。
如何设置所有这些完全取决于您自己。例如,您可以:
- 定义独立策略,并将每个策略与适当的权限关联。
- 更好的方法是,定义独立策略,然后将所有相关策略分组到一个“聚合”策略(一种“策略的策略”)下,然后将该聚合策略与基于范围的权限相关联。您可以让这种基于范围的权限适用于资源和其所有关联范围。
- 或者,您可以通过利用两种不同的类型进一步分解权限。您可以仅通过基于资源的权限类型为资源创建权限,并将其他权限与基于范围的权限类型分开关联。
您有多种选择。
如果有多个权限匹配给定的资源/范围,Keycloak会怎么做?
这取决于
- 资源服务器的“决策策略”
- 每个权限的“决策策略”
- 每个策略的“逻辑”值。
Logic
的值类似于Java的!
运算符。它可以是Positive
或Negative
。当Logic
为Positive
时,策略的最终评估保持不变。当Logic
为Negative
时,最终结果被取反(例如,如果一个策略评估为false并且其Logic
为Negative
,那么它将变为true
)。为了简单起见,让我们假设Logic
始终设置为Positive
。
真正想要解决的是Decision Strategy
。 Decision Strategy
可以是Unanimous
或Affirmative
。根据文档,
决策策略
这些配置更改了策略评估引擎如何决定是否基于所有已评估权限的结果授予资源或范围。 "肯定" 意味着至少一个权限必须评估为积极决策,才能授予对资源及其范围的访问权限。 "一致" 意味着所有权限必须评估为积极决策,才能使最终决策也是积极的。例如,如果同一资源或范围的两个权限存在冲突(其中一个授予访问权限,另一个拒绝访问权限),则如果所选策略是 "肯定",则将授予对资源或范围的许可。否则,任何权限的单个拒绝也将拒绝对资源或范围的访问。
让我们使用一个例子来更好地理解上述内容。假设您有一个资源和两个权限,并且有人正在尝试访问该资源(请记住,所有策略的逻辑都是积极的)。现在:
1. "权限一" 的 "决策策略" 设置为 "肯定"。它还有 3 个策略,每个策略的评估结果如下:
Permission Two
的决策策略
设置为Unanimous
,有两个策略:
现在进行
最终评估。如果资源服务器的
决策策略
设置为
Affirmative
,则会授予对该资源的访问权限,因为
权限一
为
true
。另一方面,如果资源服务器的
决策策略
设置为
Unanimous
,则将拒绝访问权限。
请参见:
我们将一直回顾这个问题。我将在第二部分解释如何设置资源服务器的决策策略
。
例如,我可以获得访问“账户”和“查看”范围的权限,因此我有权查看账户?
简短的回答是是的。现在,让我们详细了解一下 :)
如果您有以下情况:
- 资源服务器的
决策策略
设置为 Unanimous
或 Affirmative
- 访问
account/{id}
资源的权限为 true
- 访问
view
范围的权限为 true
您将被授予查看账户的访问权限。
Affirmative
或 Unanimous
的 决策策略
下,true
+ true
等于 true
。
现在如果您有以下内容
- 资源服务器的
决策策略
设置为 Affirmative
- 访问
account/{id}
资源的权限为 true
- 访问
view
范围的权限为 false
您同样将被授予查看账户的访问权限。
这里的重点是,访问给定资源还取决于您的设置,因此要小心,因为您可能不想要第二种情况。
但我是否正确地理解了这意味着我需要为用户可能属于的每个旧组创建一个策略?
我不确定两年前Keycloak的行为如何,但您可以指定基于组的策略,然后将所有组添加到该策略下。您确实不需要为每个组创建一个策略。
例如,如果我有"help desk"角色,那么我需要一个"help desk membership"策略,然后我可以将其添加到"viewAccount"权限中。这正确吗?
差不多。您可以以许多方式设置此项。例如,您可以:
- 创建您的资源(例如
/account/{id}
),并将其与account:view
范围关联。
- 创建一个基于角色的策略,并在该策略下添加
helpdesk
角色
- 创建一个名为
viewAccount
的Scope-Based
权限,并将其与scope
、resource
和policy
绑定
我们会在第二部分设置类似的内容。
第 II 部分
Keycloak有一个很好的小工具,可以让您测试所有策略。更好的是,您实际上不需要再启动另一个应用程序服务器并部署单独的应用程序才能使其正常工作。
这是我们要设置的方案:
- 我们将创建一个名为
stackoverflow-demo
的新领域。
- 在该领域下,我们将创建一个名为
bank-api
的客户端。
- 我们将为该客户端定义一个名为
/account/{id}
的资源。
account/{id}
将具有 account:view
范围。
- 我们将在新领域下创建一个名为
bob
的用户。
- 我们还将创建三个角色:
bank_teller
、account_owner
和 user
。
- 我们不会将
bob
与任何角色关联起来。目前不需要这样做。
我们将设置以下两个基于角色的策略:
bank_teller
和account_owner
可以访问/account/{id}
资源
account_owner
可以访问account:view
范围
user
无法访问资源或范围
我们将使用Evaluate
工具来测试如何授予或拒绝访问权限。
请原谅我,这个例子并不现实,但我不熟悉银行业务 :)
Keycloak设置
下载并运行Keycloak
cd tmp
wget https://downloads.jboss.org/keycloak/8.0.0/keycloak-8.0.0.zip
unzip keycloak-8.0.0.zip
cd keycloak-8.0.0/bin
./standalone.sh
创建初始管理员用户
- 访问
http://localhost:8080/auth
- 点击
管理控制台
链接
- 创建管理员用户并登录
欲了解更多信息,请访问 入门指南。对于我们的目的,以上内容已足够。
设置舞台
创建新领域
- 将鼠标悬停在
master
领域上,然后单击 添加领域
按钮。
- 输入
stackoverflow-demo
作为名称。
- 单击
创建
。
- 左上角现在应显示
stackoverflow-demo
而不是 master
领域。
请参阅 创建新领域。
创建新用户
点击左侧的
用户
链接
点击
添加用户
按钮
输入
用户名
(例如
bob
)
确保
启用用户
已打开
点击
保存
请参见
创建新用户
创建新角色
点击
角色
链接
点击
添加角色
添加以下角色:
bank_teller
、
account_owner
和
user
同样,不要将您的用户与角色关联。对于我们的目的,这是不必要的。
请参见
角色
创建客户端
- 点击
Clients
链接
- 点击
Create
- 在
Client ID
中输入 bank-api
- 在
Root URL
中输入 http://127.0.0.1:8080/bank-api
- 点击
Save
- 确保
Client Protocol
设置为 openid-connect
- 将
Access Type
更改为 confidential
- 将
Authorization Enabled
更改为 On
- 向下滚动并点击
Save
。新的 Authorization
选项卡应该出现在顶部。
- 点击
Authorization
选项卡,然后点击 Settings
- 确保
Decision Strategy
设置为 Unanimous
- 这是资源服务器的
Decision Strategy
参见:
创建自定义范围
- 单击“授权”选项卡
- 单击“授权范围”>“创建”以打开“添加范围”页面
- 在名称中输入“account:view”,然后按Enter键。
创建“查看账户资源”
- 点击上方的
授权
链接
- 点击
资源
- 点击
创建
- 在
名称
和显示名称
中输入查看账户资源
- 在
URI
中输入account/{id}
- 在
作用域
文本框中输入account:view
- 点击
保存
请参见创建资源
创建您的策略
再次在
Authorization
标签下,点击
Policies
从
Create Policy
下拉菜单中选择
Role
在
Name
部分输入
Only Bank Teller and Account Owner Policy
在
Realm Roles
中选择
bank_teller
和
account_owner
角色
确保
Logic
设置为
Positive
点击
Save
点击链接中的
Policies
再次从
Create Policy
下拉菜单中选择
Role
这次使用
Only Account Owner Policy
作为
Name
在
Realm Roles
中选择
account_owner
角色
确保
Logic
设置为
Positive
点击
Save
点击顶部的
Policies
链接,您现在应该能看到您新创建的策略。
查看基于角色的策略
请注意,Keycloak拥有更强大的策略功能。请查看管理策略。
创建基于资源的权限
- 再次在
授权
选项卡下,单击权限
- 选择
基于资源
- 为
名称
键入查看帐户资源权限
- 在
资源
下选择查看帐户资源
- 在
应用策略
下选择只有银行出纳和账户所有者策略
- 确保
决策策略
设置为一致
- 单击
保存
请查看创建基于资源的权限
咻...
评估基于资源的权限
再次在 授权
选项卡下,选择 评估
在 用户
下输入 bob
在 角色
下选择 user
在 资源
下选择 查看账户资源
并点击 添加
点击评估。
展开 带有作用域 [account:view] 的查看账户资源
以查看结果,您应该会看到 DENY
。
![Enter image description here](https://istack.dev59.com/MyKMU.webp)
这很有道理,因为我们只允许两个角色通过 Only Bank Teller and Account Owner Policy
访问该资源。让我们测试一下,确保这是正确的!
点击评估结果上方的 返回
链接
将 bob 的角色更改为 account_owner
,然后点击 评估
。现在您应该看到结果为 PERMIT
。如果您返回并将角色更改为 bank_teller
,则情况也是一样的。
查看评估和测试策略
创建基于范围的权限
- 返回到
权限
部分
- 这次在
创建权限
下拉菜单中选择基于范围
- 在
名称
下输入查看账户范围权限
- 在
范围
下输入account:view
- 在
应用策略
下输入仅限账户所有者策略
- 确保
决策策略
设置为一致
- 点击
保存
查看创建基于范围的权限
第二次测试运行
评估我们的新更改
- 返回到
授权
部分
- 点击
评估
- 用户应该是
bob
- 角色应该是
bank_teller
- 资源应该是
查看账户资源
,然后点击添加
- 点击
评估
,我们应该得到DENY
。
- 这应该不会让人感到惊讶,因为
bank_teller
可以访问资源
但不能访问范围
。在这里,一个权限计算结果为true,另一个为false。鉴于资源服务器的决策策略
设置为Unanimous
,最终决策是DENY
。
- 在
授权
选项卡下点击设置
,将决策策略
更改为Affirmative
,然后再次执行步骤1-6。这次,最终结果应该是PERMIT
(一个权限为true,所以最终决策为true)。
- 为了完整起见,将资源服务器的
决策策略
改回Unanimous
。再次执行步骤1到6,但这次将角色设置为account_owner
。这次,最终结果仍然是PERMIT
,这是有道理的,因为account_owner
可以访问资源
和范围
。