动手操作:一个 OAuth 2 应用程序(2) - 配置 Keycloak 为授权服务器
lipiwang 2025-05-24 15:22 3 浏览 0 评论
接上一篇《动手操作:一个 OAuth 2 应用程序(1) - 应用程序场景 》进行场景分析后,本篇就开始动手实现授权服务器。
在本文中,我们将 Keycloak 配置为系统的授权服务器 ( 图 3 )。Keycloak 是一个优秀的开源工具,专为身份和访问管理而设计。你可以从 keycloak.org 下载 Keycloak 。Keycloak 提供了本地管理简单用户的能力,还提供了高级功能,如用户联盟。您可以将其连接到 LDAP 和 Active Directory 服务或不同的身份提供者。例如,您可以使用 Keycloak 作为高级身份认证层,将其连接到我们在《 OAuth 2 是如何工作的?——(1)》中讨论过的常见 OAuth 2 提供者之一。
图 3 作为本文中实际应用程序的一部分,我们遵循三个主要步骤。在本节中,我们将 Keycloak 配置为系统的授权服务器作为第一步。
Keycloak 的配置很灵活,尽管它可以变得复杂,这取决于你想要实现什么。在本文中,我们只讨论我们的示例需要进行的设置。我们的设置仅定义了少数用户的角色。但 Keycloak 能做的远不止这些。如果您计划在实际场景中使用 Keycloak ,我建议您首先阅读其官方网站上的详细文档 :
https://www.keycloak.org/documentation。在 Ken Finnigan (Manning, 2018)的《企业Java微服务》(Enterprise Java Microservices) 的第9章中,您还可以找到作者使用 Keycloak 进行用户管理的关于保护微服务的很好的讨论。这是链接:
https://livebook.manning.com/book/enterprise-java-microservices/chapter-9
( 如果你喜欢关于微服务的讨论,我推荐你阅读 Ken Finnigan 的整本书。作者对任何用 Java实现微服务的人都应该知道的主题提供了极好的见解。)
要安装 Keycloak ,您只需下载包含官方网站
https://www.keycloak.org/downloads 的最新版本的存档。 然后,解压缩文件夹中的存档,您可以使用您在 bin 文件夹中找到的独立可执行文件启动 Keycloak 。 如果您正在使用 Linux,则需要运行 StandalOle.sh。 对于 Windows,您可以运行 Standalone.bat。
启动 Keycloak 服务器后,在浏览器 http://localhost:8080 中访问它。在 Keycloak 的第一页中,您可以通过输入用户名和密码来配置一个 admin 帐户( 图 4 )。
图 4 要管理 Keycloak,首先需要设置管理员凭证。你可以在第一次启动 Keycloak 的时候访问它。
图 5 设置好管理帐户后,就可以使用刚才设置的凭证登录 Keycloak 管理控制台
就是这样。您成功地设置了管理凭证。然后,使用凭证登录来管理 Keycloak ,如图 5 所示。
在管理控制台中,您可以开始配置授权服务器。我们需要知道 Keycloak 暴露了哪些 OAuth 2 相关的端点。您可以在 Realm Settings 页面的 General 部分中找到这些端点,这是登录到 Administration Console 后的第一个页面 ( 图 6 )。
图 6 通过单击 OpenID Endpoint Configuration 链接可以找到与授权服务器相关的端点。您需要这些端点来获取访问令牌并配置资源服务器。
在下一个代码片段中,我提取了 OAuth 2 配置的一部分,您可以通过单击 OpenID Endpoint configuration 链接找到这些配置。此配置提供令牌端点、授权端点和支持的授权类型列表。这些细节你应该很熟悉,就像我们在前面 OAuth 2 相关文章中讨论过的那样。
{
"issuer":
"http://localhost:8080/auth/realms/master",
"authorization_endpoint":
"http://localhost:8080/auth/realms/master/
protocol/openid-connect/auth",
"token_endpoint":
"http://localhost:8080/auth/realms/master/
protocol/openid-connect/token",
"jwks_uri":
"http://localhost:8080/auth/realms/master/protocol/
openid-connect/certs",
"grant_types_supported":[
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials"
],
...
}
图 7 为了测试应用程序,我们手动生成访问令牌,我们用它来调用端点。如果您为令牌定义了一个较短的生命周期,那么您需要更频繁地生成它们,当一个令牌在您可以使用它之前过期时,您可能会感到烦恼。
您可能会发现,如果您配置了长期的访问令牌,那么测试应用程序会更加方便 (图 7 )。然而,在现实场景中,请记住不要让您的令牌拥有很长的寿命。例如,在生产系统中,令牌应该在几分钟内过期。但为了进行测试,你可以让它保持活跃一天。您可以从令牌选项卡更改令牌的生命周期长度,如图 8 所示。
图 8 如果发出的访问令牌没有很快过期,您可能会发现测试更方便。您可以在 Tokens 选项卡中更改其生命周期。
现在我们已经安装了 Keycloak,设置了管理凭证,并做了一些调整,我们可以配置授权服务器了。下面是配置步骤的列表。
- 为系统注册客户端。OAuth 2 系统需要至少一个被授权服务器识别的客户端。客户端为用户发出认证请求。在 1 节中,您将学习如何添加一个新的客户端注册。
- 定义客户端作用域 ( scope )。客户端作用域标识了客户端在系统中的用途。我们使用客户端作用域定义来定制授权服务器发出的访问令牌。在第 2 节中,您将学习如何添加客户端作用域,在第 4 节中,我们将配置它以定制访问令牌。
- 为我们的应用程序添加用户。为了调用资源服务器上的端点,我们需要应用程序的用户。在 3 节中,您将学习如何添加 Keycloak 管理的用户。
- 定义用户角色和自定义访问令牌。添加用户之后,您可以为他们颁发访问令牌。您将注意到,访问令牌没有我们完成我们的场景所需的所有信息。在 4 节中,您将学习如何为用户配置角色,并定制访问令牌,以显示我们将使用 Spring Security 实现的资源服务器所期望的详细信息。
1 为系统注册客户端
在本节中,我们将讨论在使用 Keycloak 作为授权服务器时注册客户端。与任何其他 OAuth 2 系统一样,我们需要在授权服务器注册客户端应用程序。要添加新客户端,我们使用 Keycloak 管理控制台。如图 9 所示,通过导航到左侧菜单上的 Clients 选项卡,您可以找到一个客户端列表。从这里,您还可以添加一个新的客户端注册。
图 9 要添加一个新客户端,您可以使用左侧菜单上的 Clients 选项卡导航到客户端列表。在这里,您可以通过单击 Clients 表右上角的 Create 按钮来添加一个新的客户端注册。
我添加了一个名为 fitnessapp 的新客户端。这个客户端表示允许从资源服务器调用端点的应用程序,我们将在《动手操作:一个 OAuth 2 应用程序(3)》中实现。图 10 显示了添加客户端的表单。
图 10 添加客户端时,只需要给它分配一个唯一的 Client ID ( fitnessapp ),然后单击 Save
2 指定客户端作用域
在本节中,我们将为在 1 节中注册的客户端定义一个作用域。客户端作用域确定了客户的目的。我们还将在 4 节中使用客户端作用域来定制 Keycloak 发出的访问令牌。要向客户端添加作用域,我们再次使用 Keycloak 管理控制台。如图 11 所示,当从左侧菜单导航到 Client Scopes 选项卡时,您会发现一个客户端作用域列表。从这里,您还可以向列表添加一个新的客户端作用域。
通过导航到 “Client Scopes” 选项卡,可以找到所有客户端作用域的列表。
图 11 对于所有客户作用域的列表,导航到客户作用域选项卡。在这里,您可以通过单击 Client Scopes 表右上角的 Create 按钮来添加一个新的客户端作用域。
对于我们在这个实际示例中构建的应用程序,我添加了一个名为 fitnessapp 的新客户端用域。在添加新作用域时,还要确保为其设置客户端作用域的协议是 openid-connect ( 图 12 )。
注意
您可以选择的另一个协议是 SAML 2.0。Spring Security 以前为这个协议提供了一个扩展,你仍然可以在
https://projects.spring.io/Spring-Security-saml/# 快速启动。我们在本系列文章中没有讨论使用 SAML 2.0,因为它不再为 Spring Security 积极开发。此外,在应用程序中,SAML 2.0 比 OAuth 2 更不常见。
图 12 添加新的客户端作用域时,给它一个唯一的名称,并确保为所需的协议定义它。在我们的例子中,我们想要的协议是 openid-connect。
创建新角色后,将其分配给客户端,如图 13 所示。通过导航到 Clients 菜单,然后选择 Client Ccopes 选项卡,可以进入这个屏幕。
图 13 一旦你有了一个客户端作用域,你将它分配给一个客户端。在此图中,我已经将需要的作用域移动到右侧名为 Assigned Default Client Scopes 的框中。通过这种方式,您现在可以将定义的作用域用于特定的客户端。
3 添加用户并获取访问令牌
在本节中,我们为应用程序创建和配置用户。 之前,我们在 1 和 2 节中配置了客户端及其作用域。 但是,除了客户端应用程序外,我们还需要用户对资源服务器提供的服务进行身份认证和访问。 我们配置了三个用于测试应用程序的用户( 图 14 )。 我将用户命名为 Mary,Bill 和 Rachel。
图 14 通过从左边的菜单导航到 Users 选项卡,您会发现您的应用程序的所有用户列表。在这里,您还可以通过单击 Users 表右上角的 Add user 来添加一个新用户。
当在 Add user 表单中添加一个新用户时,给它一个唯一的用户名,并选中表示已验证电子邮件的框 (图 15 )。另外,确保用户没有选择 Required User Actions。当用户有 Required User Actions 挂起时,您不能将其用于身份认证;因此,您无法获得该用户的访问令牌。
图 15 添加新用户时,给用户一个唯一的用户名,并确保该用户没有 Required User Actions
创建用户后,应该在 Users 列表中找到所有用户。图 16 显示了 Users 列表。
图 16 新创建的用户现在出现在 Users 列表中您可以从这里选择一个用户来编辑或删除。
当然,用户登录也需要密码。通常,他们会配置自己的密码,而管理员不应该知道他们的凭证。在我们的示例中,除了自己为这三个用户配置密码外,别无选择 ( 图 17 )。为了使我们的示例简单,我为所有用户配置了密码 “12345”。我还通过取消 Temporary 复选框来确保密码不是临时的。如果您将密码设置为临时的,Keycloak 会在用户第一次登录时自动为用户添加一个修改密码的操作。由于这个必需的操作,我们无法对用户进行身份认证。
图 17 您可以从列表中选择一个用户来更改或配置其凭证在保存更改之前,请记住确保将 Temporary 复选框设置为 OFF。如果凭证是临时的,您将无法预先对用户进行身份认证。
配置好用户后,您现在可以从使用 Keycloak 实现的授权服务器获得访问令牌。下一个代码片段将向您展示如何使用密码授权类型获取令牌,以保持示例的简单性。然而,正如您在 1 节中观察到的,Keycloak 也支持在《OAuth 2 是如何工作的?——(1)》中讨论的其他授权类型。图 18 是我们在那里讨论的密码授权类型。
要获取访问令牌,调用授权服务器的 /token 端点:
curl -XPOST "http://localhost:8080/auth/realms/master/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=password" \
--data-urlencode "username=rachel" \
--data-urlencode "password=12345" \
--data-urlencode "scope=fitnessapp" \
--data-urlencode "client_id=fitnessapp"
图 18 当使用密码授权类型时,用户与客户端共享他们的凭证。客户端使用凭证从授权服务器获取访问令牌。有了令牌,客户端就可以访问由资源服务器公开的用户资源。
您在 HTTP 响应体中接收访问令牌。下面的代码片段显示了响应:
{
"access_token":"eyJhbGciOiJIUzI...",
"expires_in":6000,
"refresh_expires_in":1800,
"refresh_token":"eyJhbGciOiJIUz... ",
"token_type":"bearer",
"not-before-policy":0,
"session_state":"1f4ddae7-7fe0-407e-8314-a8e7fcd34d1b",
"scope":"fitnessapp"
}
注意
在 HTTP 响应中,我截短了 JWT 令牌,因为它们很长。
下一个代码片段表示 JWT 访问令牌的解码 JSON 体。看一下代码片段,您可以观察到令牌不包含使应用程序工作所需的所有详细信息。角色和用户名缺失。在 4 节中,您将学习如何将角色分配给用户,并自定义 JWT 以包含资源服务器需要的所有数据。
{
"exp": 1585392296,
"iat": 1585386296,
"jti": "01117f5c-360c-40fa-936b-763d446c7873",
"iss": "http://localhost:8080/auth/realms/master",
"sub": "c42b534f-7f08-4505-8958-59ea65fb3b47",
"typ": "Bearer",
"azp": "fitnessapp",
"session_state": "fce70fc0-e93c-42aa-8ebc-1aac9a0dba31",
"acr": "1",
"scope": "fitnessapp"
}
4 定义用户角色
在第 3 节中,我们设法获得了一个访问令牌。我们还添加了一个客户端 , 并配置用户以获得令牌。但是,令牌仍然没有我们的资源服务器应用授权规则所需的所有信息。要为我们的场景编写一个完整的应用程序,我们需要为用户添加角色。
向用户添加角色很简单。左侧菜单中的 Roles 选项卡允许您查找所有角色的列表并添加新角色,如图 19 所示。我创建了两个新角色,fitnessuser 和 fitnessadmin。
图 19 通过访问左侧菜单中的 Roles 选项卡,您可以找到所有已定义的角色,并可以创建新的角色。然后将它们分配给用户。
现在我们将这些角色分配给用户。我将角色 fitnessadmin 分配给我们的管理员 Mary,而 Bill 和 Rachel,他们是普通用户,担任角色 fitnessuser。图 20 向您展示了如何将角色附加到用户。
图 20 在所选用户的角色映射部分中,您分配角色。这些角色映射作为访问令牌中的用户权限显示,您可以使用它们来实现授权配置。
不幸的是,默认情况下,这些新的详细信息不会出现在访问令牌中。我们必须根据应用程序的需求定制令牌。我们通过配置在 2 节中创建并分配给令牌的客户端范围来定制令牌。我们需要向我们的令牌添加更多的三个信息:
- Roles — 用于根据场景在端点层应用部分授权规则
- Username — 在应用授权规则时过滤数据
- Audience claim (aud) — 资源服务器用来确认请求,您将在《动手操作:一个 OAuth 2 应用程序(3)》中了解到这一点。
下一个代码片段显示了在我们完成设置后添加到令牌的字段。然后,我们通过在客户端作用域上定义映射器来添加自定义声明,如图 21 所示。
{
// ...
"authorities": [
"fitnessuser"
],
"aud": "fitnessapp",
"user_name": "rachel",
// ...
}
图 21 我们为特定客户端作用域创建映射器来定制访问令牌。通过这种方式,我们提供了资源服务器授权请求所需的所有详细信息。
图 22 显示了如何创建映射器来将角色添加到令牌。我们在令牌中添加带有 authorities 键的角色,因为这是资源服务器所期望的方式。
图 22 为了在访问令牌中添加角色,我们定义了一个映射器。添加映射器时,需要为其提供一个名称。我们还指定要添加到令牌的详细信息和标识分配的详细信息的声明的名称。
使用类似于图 22 所示的方法,我们还可以定义一个映射器来将用户名添加到令牌。图 23 显示了如何为用户名创建映射器。
图 23 我们创建一个映射器将用户名添加到访问令牌当将用户名添加到访问令牌时,我们选择声明的名称 user_name,这是资源服务器期望在令牌中找到它的方式。
最后,我们需要指定受众。受众声明 ( aud ) 定义了访问令牌的预期接收者。我们为这个声明设置了一个值,并为资源服务器配置了相同的值,您将在《动手操作:一个 OAuth 2 应用程序(3)》中了解到这一点。图 24 向您展示了如何定义映射器,以便 Keycloak 可以将 aud 声明添加到 JWT。
图 24 表示映射器类型 Audience 的 aud 声明定义了访问令牌的接收者,在我们的例子中,是资源服务器。我们在资源服务器端配置相同的值,以便资源服务器接受令牌。
如果您再次获得访问令牌并对其进行解码,您应该在令牌的主体中找到 authorities、user_name 和 aud 声明。现在,我们可以使用这个 JWT 对资源服务器公开的端点进行身份认证和调用。现在我们已经在第 3 节中配置了一个完整的授权服务器,我们将为《动手操作:一个 OAuth 2 应用程序(1)》中介绍的场景实现资源服务器。下面的代码片段显示了令牌的主体:
{
"exp": 1585395055,
"iat": 1585389055,
"jti": "305a8f99-3a83-4c32-b625-5f8fc8c2722c",
"iss": "http://localhost:8080/auth/realms/master",
"aud": "fitnessapp",
"sub": "c42b534f-7f08-4505-8958-59ea65fb3b47",
"typ": "Bearer",
"azp": "fitnessapp",
"session_state": "f88a4f08-6cfa-42b6-9a8d-a2b3ed363bdd",
"acr": "1",
"scope": "fitnessapp",
"user_name": "rachel",
"authorities": [
"fitnessuser"
]
}
Keycloak 授权服务器我们已经基本配置好,下一篇我们就可以开始讨论资源服务器的实现。
相关推荐
- httpclient+jsoup实现小说线上采集阅读
-
前言 用过老版本UC看小说的同学都知道,当年版权问题比较松懈,我们可以再UC搜索不同来源的小说,并且阅读,那么它是怎么做的呢?下面让我们自己实现一个小说线上采集阅读。(说明:仅用于技术学习、研究) ...
- Python3+requests+unittest接口自动化测试实战
-
一、Requests介绍RequestsisanelegantandsimpleHTTPlibraryforPython,builtforhumanbeings.翻译过来就是...
- 授权码 + PKCE 模式|OIDC & OAuth2.0 认证协议最佳实践系列【03】
-
在上一篇文章中,我们介绍了OIDC授权码模式,本次我们将重点围绕授权码+PKCE模式(AuthorizationCodeWithPKCE)进行介绍,从而让你的系统快速具备接入用户认...
- JWT 在 Java Web 开发中的奇妙应用
-
JWT在JavaWeb开发中的奇妙应用在当今的互联网世界里,安全始终是一个绕不开的话题。而当我们谈论到Web应用的安全性时,认证和授权绝对是其中的核心部分。说到这,我忍不住要给大家讲个笑话...
- 动手操作:一个 OAuth 2 应用程序(2) - 配置 Keycloak 为授权服务器
-
接上一篇《动手操作:一个OAuth2应用程序(1)-应用程序场景》进行场景分析后,本篇就开始动手实现授权服务器。在本文中,我们将Keycloak配置为系统的授权服务器(图3)。...
- JSON Web Token是什么?
-
JSONWebToken(缩写JWT)是目前最流行的跨域认证解决方案。传统的session认证http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证...
- Keycloak Servlet Filter Adapter使用
-
KeycloakClientAdapters简介Keycloakclientadaptersarelibrariesthatmakeitveryeasytosecurea...
- 使用JWT生成token
-
一、使用JWT进行身份验证1、传统用户身份验证Internet服务无法与用户身份验证分开。一般过程如下:用户向服务器发送用户名和密码。验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中...
- 在word中通过VBA调用百度翻译API在线翻译
-
一天的时间,借助各种AI终于解决了这个问题:在word中通过VBA调用百度翻译API进行在线翻译。给我的word又添加了一项神技。先上代码:Sub宏5()''宏5宏Dimapp...
- API 安全之认证鉴权
-
作者:半天前言API作为企业的重要数字资源,在给企业带来巨大便利的同时也带来了新的安全问题,一旦被攻击可能导致数据泄漏重大安全问题,从而给企业的业务发展带来极大的安全风险。正是在这样的背景下,Ope...
- 用WordPress建站哪些插件会拖慢速度影响排名?
-
你是否发现网站加载总慢半拍,SEO排名死活上不去?八成是插件惹的祸!80%的站长不知道,WordPress插件用错类型或配置不当,分分钟让网站速度暴跌,爬虫抓取效率直接砍半。缓存插件没装对,越用越卡你...
- JavaScript报错了?不要慌!怎么看怎么处理都在这里
-
在开发中,有时,我们花了几个小时写的JS代码,在游览器调试一看,控制台一堆红,瞬间一万头草泥马奔腾而来。至此,本文主要记录JS常见的一些报错类型,以及常见的报错信息,分析其报错原因,并给予处理...
-
- 跨站脚本攻击(四)
-
04XSS漏洞挖掘技巧4.1常见的绕过姿势实际应用中web程序往往会通过一些过滤规则来阻止带有恶意代码的用户输入被显示,但由于HTML语言的松散性和各种标签的不同优先级,使得我们绕过过滤规则成为了可能。4.1.1利用大小写绕过HTML标签...
-
2025-05-24 15:21 lipiwang
- WAF-Bypass之SQL注入绕过思路总结
-
过WAF(针对云WAF)寻找真实IP(源站)绕过如果流量都没有经过WAF,WAF当然无法拦截攻击请求。当前多数云WAF架构,例如百度云加速、阿里云盾等,通过更改DNS解析,把流量引入WAF集群,流量经...
- Springboot之登录模块探索(含Token,验证码,网络安全等知识)
-
简介登录模块很简单,前端发送账号密码的表单,后端接收验证后即可~淦!可是我想多了,于是有了以下几个问题(里面还包含网络安全问题):1.登录时的验证码2.自动登录的实现3.怎么维护前后端登录状态在这和大...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)