本文译自Keycloak官方文档,原文链接。对应版本为5.0。
概述
Keycloak支持细粒度的授权策略,并可以对这些策略进一步组合,如:
- 基于属性(ABAC)
- 基于角色(RBAC)
- 基于用户(UBAC)
- 基于上下文(CABC)
- 基于规则(Rule-based)
- 通过JavaScript
- 使用Jboss Drools
- 基于时间(Time-based)
- 通过SPI自定义访问控制策略(ACM)
Keycloak提供了一组管理界面和RESTful API,用于创建权限、关联权限与授权策略,以及在应用程序中执行授权决策。
资源服务器需要依据一些信息才能判断权限。对于REST的资源服务器来说这些信息通常来自于一个加密的token,如在每个访问请求中携带bearer token。对于依赖于session的Web应用来说,这些信息就来自于每个request对应的用户session。
资源服务器通常执行的是基于角色的访问控制(RBAC)策略,即检查用户所拥有的角色是否关联了要访问的资源。虽然这种方式非常有用,但是它们也有一些限制:
- 资源和角色紧耦合,角色的更改(如添加、删除或更改访问上下文)可能影响多个资源。
- 基于RBAC的应用程序无法很好地响应安全性需求的调整。
- 项目规模扩大时,复杂的角色管理会很困难而且容易出错。
- 不够灵活。角色并不能有效代表用户身份,即缺乏上下文信息。客观上来说被授予了角色的用户,至少会拥有某些访问权限。
当下的项目中,我们需要考虑不同地区、不同本地策略、使用不同设备、以及对信息共享有较高需求的异构环境。Keycloak授权服务可以通过以下方式帮助您提高应用程序和服务的授权能力:
- 不同的访问控制机制以及细粒度的授权策略。
- 中心化的资源、权限以及策略管理。
- 中心化的策略决策。
- REST风格的授权服务。
- 授权工作流以及用户访问管理。
- 可作为快速响应您项目中安全需求的基础设施。
架构
从设计的角度来看,授权服务基于一组授权模式,提供了以下功能:
- 策略管理点(PAP)
在Keycloak Admin的基础上提供了UI界面来管理资源服务器、资源、范围、权限以及策略。其中的部分功能也可以通过Protection API来实现。
- 策略决策点(PDP)
为和权限请求相应的授权请求以及策略评估,提供了分布式的策略决策点。更多信息请查看获取权限章节。
- 策略执行点(PEP)
为资源服务器端实际执行授权决策,Keycloak提供了用于不同环境的一些内置策略执行器。
- 策略信息点(PIP)
基于Keycloak的认证服务器,可以在策略评估时从身份认证信息以及上下文环境中获取一些其它属性。
授权过程
Keycloak的细粒度授权主要有三个必要步骤:
- 资源管理
- 权限及策略管理
- 执行策略
资源管理
资源管理定义了什么是被保护的对象。
首先,需要定义被保护的资源服务器,通常是一个web应用或一组服务。有关资源服务器的更多信息请参考术语。
资源服务器可以使用Keycloak管理员控制台来管理。在那里,您可以将任何已注册的客户端启用为资源服务器,并管理其资源和范围。
资源可以是web页面、Rest资源、文件系统上的一个文件、一个EJB等等。它们可以是一组资源(如Java中的一个Class),也可以是一个特定的资源。
举例来说,你可以用Bank Account来代表所有的银行账户,并且用它来定义对全部银行账户的通用授权。但同时你也可以为Alice的私有账户来单独设置权限,使得只有Alice本人能够对其账户进行某些操作。
资源可以通过Keycloak控制台或者Protection API来管理。利用Protection API的方式,资源服务器可以远程管理资源。
范围(Scope)通常用来表示在资源上执行的动作,还可以使用范围来代表资源中的一个或者多个属性。
权限及策略管理
定义好了资源服务器和其上的资源,下一步就是定义权限和策略。
定义策略的步骤图示如下:
策略定义了在资源或者范围上执行某些动作的先决条件,但是请记住它们并不和被保护的资源直接绑定。策略是通用的,可以通过再次组合来构造更复杂的权限及策略。
举例来说,要获取“User Premium”角色下的资源组访问权限,你可以使用RBAC策略。
Keycloak为常用场景提供了一些内置的策略类型。你可以使用JavaScript或者JBoss的Drools来编写自己的策略。
定义了策略之后就可以来定义权限了。权限与被保护的资源紧耦合,它们由被保护对象及策略组合而成。
执行策略
策略的执行包含了对资源服务器实际实施授权决策的必要步骤。实现方式是在资源服务器上启用策略执行点(PEP),PEP能够与授权服务器通信,请求授权数据,并根据服务器返回的决策来控制对受保护资源的访问。
Keycloak提供了一些内置的PEP实现,你可以根据项目运行平台来自由选择。
授权服务
授权服务包括下列三种REST端点:
- Token Endpoint
- Resource Management Endpoint
- Permission Managerment Endpoint
上边的各个端点涵盖了授权服务的各个步骤。
Token Endpoint
Oauth2客户端(如前端应用)可以通过token endpoint获取访问令牌(access token),然后使用这些令牌来获取资源服务器(如后端应用)上被保护的资源。同样,Keycloak授权服务扩展了OAuth2,允许基于配置好的策略发放访问令牌。这意味着资源服务器可以利用关联了权限的令牌来对资源进行保护。在Keycloak中,带有权限的访问令牌被称作请求方令牌(Requesting Party Token),或者缩写为RPT。
更多的信息请查看获取权限章节。
保护API
保护API指提供的一系列UMA兼容的操作,用来帮助资源服务器管理资源、范围、权限及相关策略。只有资源服务器才能被允许访问这些API,前提是资源服务器有内置的uma_protection范围。
提供给资源服务器的API可以分为两组:
- 资源管理
创建资源、删除资源、根据ID查询、其他查询
- 权限管理
发放权限Ticket
远程管理资源的功能默认是开启的。可以通过Keycloak管理员控制台来关闭此功能。
如果使用了UMA协议,Protection API对权限Ticket的发放是整个授权流程的重要组成部分。后面会讲到,它们表示着在整个授权过程中客户端所申请的权限及向服务器申请包含着权限的最终令牌。
更多信息请查看保护API章节。
名词解释
在深入到Keycloak前我们需要解释一下Keycloak授权服务中所用到的专有名词。
资源服务器(Resource Server)
如前所述,资源服务器通常依赖某种信息来决定是否授权。该授权信息通常包含在安全令牌或用户会话中。
任何可信的Keycloak客户端都可以作为资源服务器。这些客户端的资源及范围由一系列的授权策略保护。
资源
资源是应用或者组织的资产。它们可以是一些列的端点、一个典型的HTML页面等等。在授权策略语境中,资源指的就是被保护的对象。
每个资源或者每组资源都有着唯一标识。请回想上文的Bank例子。
范围
资源的范围扩展了资源的访问界限。在授权语义中,范围是可以应用在资源上的许多动词之一。
它通常表示对指定资源可施加的动作。如查看、编辑、删除等等。但是范围也可以表示资源的其它关联信息。如工程资源和造价范围,这里的造价范围被用来定义用户访问工程造价的特定策略及权限。
权限
权限将被保护的对象与必须评估的策略关联起来,以确定是否允许访问。
- X 可以在资源 Z 上施加 Y
这里X指可以是用户、角色、用户组,或者其组合。在这里你可以使用声明和上下文。
Y指代一个动作,如写、读等等。
Z指代被保护的资源,如 "/accounts"。
Keycloak提供了丰富的平台用于构建从简单到复杂的权限策略,如基于规则的权限控制。使用Keycloak可以带来:
- 减少代码重构和权限管理成本。
- 支持灵活的安全模型,用以应对安全模型可能的变化。
- 支持运行时变化。应用系统只需要关心资源和范围,Keycloak隐藏了它们如何被保护的细节
策略
策略定义了授予对象访问权时必须满足的条件。与权限不同,策略不指定受保护的对象,而是指定访问制定对象(如资源、范围或两者)时必须满足的条件。策略与用来保护资源的访问控制机制(ACMs)密切相关。使用策略可以实现基于属性的访问控制(ABAC)、基于角色的访问控制(RBAC)、基于上下文的访问控制以及其任何组合。
Keycloak还提供了聚合策略,即“策略的策略”。在构造复杂的访问控制条件时,Keycloak授权服务遵循了分而治之的原则。你可以创建独立的策略,并在不同的权限中使用它们,然后通过组合它们来构造更复杂的策略。
策略提供者(Policy Provider)
策略提供者是特定策略类型的具体实现。Keycloak提供的内置策略都是由不同的提供者来支持的。Keycloak允许添加自定义的策略类型。
Keyclaok提供了SPI(Service Provider Interface),你可以使用SPI来添加自定义策略提供者。
权限许可(Permission Ticket)
权限许可(权限ticket)是由UMA定义的特殊token类型,它的不透明结构由授权服务器所决定。这种结构代表了客户端请求的资源或者范围、访问上下文,以及要执行的策略。
在UMA中,权限许可是人与人、人与组织之间共享的关键。在授权工作流中使用权限ticket可以支持一系列从简单到复杂的场景,让资源所有者和资源服务器细粒度地控制资源访问。
在UMA工作流中,授权服务器向资源服务器发出权限ticket,资源服务器将ticket返回给试图访问受保护资源的客户端。客户端拿到ticket就可以通过将它发送回授权服务器来请求RPT(最终的包含授权数据的令牌)。
开始
在使用本教程之前,请确保正确安装了Keycloak并已经初始化了管理员账户。注意,你必须在Keycloak同一台主机上运行独立的WildFly实例。这个独立的实例将用来运行你的Java Servlet应用。你可以在启动命令中使用jboss.socket.binding.port-offset来避免端口冲突。
可以用如下命令来启动Keycloak服务(Linux版):
$ .../bin/standalone.sh -Djboss.socket.binding.port-offset=100
Windows版:
> ...\bin\standalone.bat -Djboss.socket.binding.port-offset=100
更多安装配置WildFly的细节请查看这里。
正确安装启动之后,可以从 http://localhost:8180/auth/admin 访问Keycloak控制台,以及从 http://localhost:8080 访问WildFly实例。
保护Servlet应用
本入门指南旨在让您尽快启动、运行及测试Keycloak提供的各种授权特性。它主要依赖于默认的数据库和服务器配置,并不涉及复杂的部署选项。有关特性或配置选项的更多信息,请参阅本文档中的相关部分。
本指南阐述了Keycloak授权服务的关键概念:
- 为客户应用提供细粒度的授权
- 将客户应用设置为资源服务器并保护其资源
- 定义权限及授权策略来保护资源
- 在应用中启用PEP
创建域(Realm)及用户
首先来创建域及域中的用户。然后在域中创建客户应用,即需要保护的资源服务器。
依照以下步骤来创建域及用户:
1. 创建名为 hello-world-authz 的域。创建成功之后的页面如下图:
2. 创建用户。点击 Users,打开用户列表页。
3. 在右侧空白的用户列表页点击 Add User。
4. 填写Username、Email、First Name及Last Name,打开User Enabled选项,然后点击 Save。
5. 在Credentials选项卡修改用户密码。
6. 填写New Password、及Password Confirmation,然后关闭Temporary。
7. 点击Reset Password完成设置用户密码。
启用授权服务
你可以为已有的客户端应用开启OpenID Connect协议。也可以创建一个新的客户端。
依照以下步骤来创建新客户端:
1. 点击Clients来创建一个新的应用,并填写Client ID,Client Protocol,以及Root URL。
2. 点击Save。
3. 开启Authorization Enabled开关,会打开新的Authorization选项卡。
4. 点击Authorization选项卡:
一旦为客户端应用开启了授权服务,Keycloak会自动创建一些授权默认配置。
有关授权配置的更多信息,请查看开启服务授权章节。
构建、部署及测试
到这里,app-authz-vanilla资源服务器应该已经被正确配置完毕了,现在我们开始部署。项目可以在这里直接下载。部署及构建的前置要求如下:
- Java JDK 8
- Apache Maven 3.1.1或更高版本
- Git
项目基于最新的Keycloak版本。可以使用如下命令来克隆代码:
$ git clone https://github.com/keycloak/keycloak-quickstarts
要构建的项目地址在:
$ cd keycloak-quickstarts/app-authz-jee-vanilla
获取适配器配置
构建项目之前请依照以下步骤来获取适配器配置。
1. 点击Clients。在client列表中,点击app-authz-vanilla。
2. 点击 Installation 选项卡。在下拉列表中选中Keycloak OIDC JSON格式。然后点击Download。
3. 将keycloak.json移到app-authz-jee-vanilla/config目录。
4. 默认情况下,访问无权限的资源时Policy执行器会返回403。你也可以定义一个重定向页面。要定义重定向页面需要修改第3步中keycloak.json文件的policy-enforcer配置:
- "policy-enforcer": {
- "on-deny-redirect-to" : "/app-authz-vanilla/error.jsp"
- }
上面的配置将403重定向到一个错误页面。
构建及部署应用
执行下面的命令来构建、部署应用:
- $ cd redhat-sso-quickstarts/app-authz-jee-vanilla
- $ mvn clean package wildfly:deploy
测试应用
如果成功部署了应用,你可以从 http://localhost:800/app-authz-vanilla 来访问Keycloak登录页。
使用刚创建的alice用户登录。
在为客户端启用授权服务时,Keycloak默认提供了一个简单的策略,该策略授予所有保护的资源以访问权限。
现在你可修改默认的权限及策略,然后来测试程序的响应,或者使用不同的策略类型来创建新的策略。
可以点击Authorization选项卡中的Policies选项卡,然后点击Default Policy来修改:
- // The default value is $evaluation.grant(),
- // let's see what happens when we change it to $evaluation.deny()
- $evaluation.deny();
现在,退出demo应用并重新登录。你会发现无法访问它了:
现在我们不更改默认的策略代码,而是将策略代码文本区域下方的Logic更改为Negative。这将重新启用对应用程序的访问,默认情况下,该策略拒绝所有访问请求。同样,在测试此更改之前请记得注销并重新登录。
下一步
我们还可以:
- 创建一个范围,定义一个策略及它的权限,然后在应用端来进行测试。看用户是否能够执行动作(或者你刚刚创建的范围)?
- 创建不同类型的策略,如基于规则的,并将这些策略和默认权限关联起来。
- 对默认权限应用多个策略并测试。例如,组合多个策略并相应地更改决策策略(Decision Strategy)。
- 关于查看及测试权限的更多信息,可以查看获取授权上下文章节。
授权快速入门
除了app-authz-jee-vanilla快速开始指南,Keycloak Quickstarts仓库中也包含本文档中的其他例子。
授权快速开始指南只是一个起点,用于帮助你快速浏览在各种场景下keycloak提供的不同技术以及集成方式。它并不是一个全面的用户手册。
每个快速开始的项目都有一个README文档来介绍如何构建、部署及测试。下表是一个简单的介绍:
Name | Description |
---|---|
app-authz-jee-servlet | 介绍在Java EE项目中如何精细化管理权限,并基于从Keycloak服务器获取到的权限来动态构建菜单 |
app-authz-jee-vanilla | 介绍在Java EE项目中如何精细化管理权限,并使用默认的授权设置来保护资源 |
app-authz-rest-springboot | 介绍如何使用Keycloak授权服务来保护SpringBoot项目 |
app-authz-springboot | 介绍如何用切面来认证并授权SpringBoot REST服务 |
app-authz-uma-photoz | 这是一个简单的基于HTML5+AngularJS+JAX-RS的项目,用来展示如何使用UMA来让用户管理自己的权限 |
管理资源服务器
根据OAuth2规范,资源服务器托管资源,并接受和响应对受保护资源的请求。
Keycloak为资源服务器提供了一个丰富的平台,用于为受保护的资源启用细粒度授权,并可以根据不同的访问控制机制来决策授权。
可以为任意客户端开启细粒度授权。这样做的时候你其实已经将一个客户端当做了一个资源服务器。
创建客户端应用程序
要开启Keycloak授权服务,必须先创建一个资源服务器。
1. 点击Clients
2. 在上面的页面中点击 Create。
3. 输入Client ID。如my-resource-server。
4. 输入Root URL。如:
http://${host}:${port}/my-resource-server
5. 点击 Save。然后开始配置client设置:
开启授权服务
将Authorization Enabled开关设置为ON并保存,就可以将OIDC 客户端设为一个资源服务器并开启细粒度授权。
上面的操作会打开新的Authorization选项卡:
Authorization选项卡下方会带有子选项卡。我们后边会讲解每个子选项卡的作用。先来快速浏览一下主要功能:
- Settings
包含资源服务器的常规设置。更多细节请查看这里。
- Resource
在这里可以管理客户端应用的资源。
- Authorization Scopes
在这里管理范围。
- Policies
在这里管理策略,以及定义授权时必须满足的条件。
- Permissions
在这里可以通过将资源/范围和策略关联起来来设置它们的权限。
- Evaluate
在这里模拟授权场景,并观察结果是否和预期一致。
- Export Settings
在这里可以导出授权配置到JSON文件。
资源服务器设置
在资源服务器设置页面可以设置策略执行模式,是否允许远程资源管理,并可以导出授权配置。
- 策略执行模式
- 强制 默认模式,对没有关联策略的资源的访问会直接被拒绝。
- 自由 对没有关联到策略的资源的访问会被允许。
- 禁用 禁用所有策略的评估,并直接允许访问。
- 远程资源管理
定义资源是否可被远程管理,关闭后资源仅能在管理员控制台管理。
默认配置
创建好了资源服务器,Keycloak会为其自动创建默认配置。
默认配置包括了:
- 一个默认的受保护资源(