简介

我们经常不考虑前端、后端或 API 应用程序的安全性;这是一个很大的错误!而且很多时候,以后添加它会更难。

所以我们需要提前考虑安全性。

但问题是:我们在这里需要什么样的安全性?

事实上,安全是一个很大的,甚至是巨大的话题。

我们这里主要关注两个方面:

  • 身份验证:检查我们是谁/我们是谁。

  • 授权:检查我们是否被允许做一个动作。

但首先,我们需要一个服务器来处理身份验证和授权。因为相信我,我们不会自己实施,这太疯狂了。

为此,我们将使用 Keycloak,这是一个用于验证和授权帐户的开源工具。

重要提示:此博客面向开发人员,因此我们不会展示如何使用生产配置安装 Keycloak。这是基础架构团队的工作

在这里,我们将向您展示如何获得开发环境并安装 Keycloak,以便我们可以在我们的应用程序上开发和测试我们的身份验证和授权。

我们将通过选择基于 OAuth 2.0 的 OpenID Connect 在 Keycloak 中使用以下协议。 OpenID Connect 扩展了它。

此外,本博客不会关注这些协议是用来保护我们的应用程序的。

如果您需要知道这些协议是什么,请访问:

https://auth0.com/docs

https://openid.net/connect/

我们只是想在这里实用一些,向您展示如何使用 Keycloak。

1\。 KeyCloak Docker 安装和管理

什么是钥匙斗篷?它是“身份和访问管理”的工具。此外,Keycloak 是一个开源工具,目前已获得 Apache License 2.0 许可。

支持平台的完整列表取决于您决定使用的协议,目前 Keycloak 支持三种不同的协议,可以在文档中查看。

钥匙斗篷功能

多种协议支持

至于目前 Keycloak 支持三种不同的协议,即

  • OpenID 连接

  • OAuth 2.0

  • SAML 2.0。

我们将在这里重点介绍 OpenID Connect 协议

SSO

Keycloak 完全支持单点登录和单点注销。

管理控制台

Keycloak 提供基于 Web 的 GUI,您可以在其中“单击”实例所需的所有配置,以按您的意愿工作。

用户身份和访问权限

通过允许我们创建具有自定义角色和组的用户数据库,Keycloak 可以用作独立的用户身份和访问管理器。此信息可进一步用于对我们应用程序中的用户进行身份验证,并根据预定义的角色保护其中的部分内容。

外部身份源同步

如果您的客户当前拥有某种类型的用户数据库,Keycloak 允许我们与此类数据库同步。默认情况下,它支持 LDAP 和 Active Directory,但您可以使用 Keycloak 用户存储 API 为任何用户数据库创建自定义扩展。请记住,这样的解决方案可能没有 Keycloak 完全运行所需的所有数据,因此请记住检查您所需的功能是否有效。

身份代理

Keycloak 也可以作为您的用户和一些外部身份提供者或提供者之间的代理。他们的列表可以从 Keycloak 管理面板中编辑。社交身份提供者 此外,Keycloak 允许我们使用社交身份提供者。它内置了对 Google、Twitter、Facebook、Stack Overflow 的支持,但最终,您必须从管理面板手动配置所有这些。可以在 Keycloak 文档中找到支持的社交身份提供者的完整列表及其配置手册。页面自定义 Keycloak 允许您自定义它向用户显示的所有页面。这些页面采用 .ftl 格式,因此您可以使用经典的 HTML 标记和 CSS 样式来使页面适合您的应用程序样式和公司品牌。您甚至可以将自定义 JS 脚本作为页面自定义的一部分,因此可能性是无限的。这些就是我今天要描述的所有 Keycloak 功能。当然,这个工具提供了更多的可能性,在文档中以更详细的方式进行了描述。

_ Keycloak 的分布 _

目前,Keycloak 有三个主要的发行版。

服务器

可以从 Keycloak 页面以 tar 或 zip 存档的形式下载独立应用程序,其中包含正常工作所需的所有脚本、文档和资产。目前,该发行版有两个主要版本:一个由 WildFly 服务器提供支持,另一个由 Quarkus 提供支持。它现在处于预览阶段,因此可能会出现一些意外错误。

码头工人形象

适用于 Docker、Podman、Kubernetes 和 OpenShift 的分发。 Keycloak 有两个官方 docker 镜像:一个保存在 Quay Container Registry -quay.io/keycloak/keycloak,第二个保存在 Docker Hub - jboss/keycloak。您可以使用简单的 docker pull 命令下载它们。

操作员

基于 Operator SDK 的 Kubernetes 和 OpenShift 分发版。如您所见,每个人都可以找到合适的分布。如果你使用 Docker 或 Kubernetes,你有 Keycloak 镜像和操作符。另一方面,如果您更喜欢更传统的部署类型,您也可以找到适合您的发行版。即便如此,Keycloak Docker 映像对于开发和测试也非常有用。

您可以设置您的测试 Keycloak 服务器,然后进行更改并测试它们。测试后,您可以重新启动 Docker 映像,对 Keycloak 所做的所有更改都将恢复,您将获得一个清晰的环境以进行进一步的测试。所有三个发行版都可以从这里下载。

我们将使用 Docker 映像,因为它是设置它的最快和最简单的方法。

我们将使用 Docker Desktop for Windows 设置 Keycloak。我们将为我们的应用程序创建一个领域和一个客户端。

别担心,我们会解释这些术语的含义。

领域

领域是您管理对象的空间,例如:

  • 用户

  • 应用程序

  • 角色

默认情况下,Keycloak 中有一个名为 master 的领域。我们将创建一个名为“MyRealm”的领域。

客户

为了保护我们的应用程序,我们需要在“MyRealm”领域内将其注册为客户端。

所以让我们开始吧。

首先我们需要安装 Docker Desktop

下载 Docker 桌面

为 Windows 安装 Docker 桌面

为 Mac 安装 Docker 桌面

为 Linux 安装 Docker 桌面

安装并启动后,我们应该在 Windows 上看到:

image.png

现在让我们从 docker 存储库quay.io/keycloak/keycloak使用本博客发布时的最新版本运行 keycloak:

您可以在以下链接中阅读有关如何使用 Docker 开始 Keycloak 的完整教程:

使用 Docker 启动 Keycloak

我们将向您展示比教程更多的细节。

如果您在 Windows 上,让我们在您的 WSL 或 shell 或 powershell 中运行以下命令。

docker run -d -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:18.0.0 start-dev

这是使用 WSL2 的链接

Docker 桌面 WSL 2 后端

在命令中,我们将主机的 8080 端口映射到容器的 8080 端口。您必须确保该端口在您的主机上是空闲的。

我们使用管理员帐户:admin 和密码 admin,但我们可以将其更改为您想要的任何登录名/密码!

运行命令后,您应该会看到正在运行的容器的 id:

image.png

λ docker run -d -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:18.0.0 start-dev
6425fce35b6b58af202fd0ff90dd206683d4fc3c21212ba804402c2d72c749a8

您还可以使用 Docker Desktop 检查正在运行的 Keycloak 容器

image.png

您可以使用浏览器获取 Keycloak。

image.png

它将打开您的默认浏览器

image.png

您还可以检查日志

首先点击那里:

image.png

然后点击日志

image.png

您还可以检查正在运行的应用程序,例如环境变量、绑定端口

image.png

现在我们将管理 Keycloak。

单击管理控制台链接

image.png

您将需要使用管理员登录名和密码。

image.png

登录后,我们得到以下页面

image.png

首先要做的是创建我们的领域:MyRealm。转到左上角菜单“大师”u003d>然后单击按钮“添加领域”

image.png

我们会得到以下页面:

image.png

我们提供信息

image.png

然后我们点击“创建”按钮。

我们收到以下消息“成功!领域已创建”,并显示以下领域设置页面:

image.png

现在我们可以将我们的应用程序添加为客户端,单击“客户端”菜单

image.png

然后我们点击“创建”按钮创建我们的客户

image.png

我们将命名为“MyApp”,并让客户端协议默认设置为“openid-connect”。

您可以了解更多关于协议的信息

OpenId

您可以看到 OpenId 派生自另一个协议 0Auth

image.png

image.png

点击“保存”按钮

image.png

我们得到以下页面

image.png

我们得到以下属性:

  • 客户端 ID:指定在 URI 和令牌中引用的 ID。例如“我的客户”。对于 SAML,这也是来自 authn 请求的预期颁发者值。在我们的例子中,它将是“MyApp”

  • 名称:指定客户端的显示名称。例如“我的客户”。也支持本地化值的键。例如:${my_client},我们不需要它。

  • 描述:指定客户端的描述。例如“我的 TimeSheets 客户”。也支持本地化值的键。例如:${my_client_description}

  • 已禁用:已禁用的客户端无法启动登录或获取访问令牌。

我们将留下以下选项:

  • 客户端协议:openid-connect

  • 访问类型:public

  • 标准流启用 u003d "ON"

  • 直接访问 Grand Enabled u003d "ON"

我们需要添加

  • 有效重定向 URI :浏览器在成功登录或注销后可以重定向到的有效 URI 模式。允许使用简单的通配符,例如“example.com”。也可以指定相对路径,例如 /my/relative/path/。相对路径是相对于客户端根 URL 的,或者如果没有指定,则使用身份验证服务器根 URL。对于 SAML,如果您依赖登录请求中嵌入的消费者服务 URL,则必须设置有效的 URI 模式。

  • Web 来源:允许的 CORS 来源。要允许有效重定向 URI 的所有来源,请添加“+”。不过,这不包括“”通配符。要允许所有来源,请显式添加“”。

但首先让我们创建我们的 React 应用程序。

2\。使用 Typescript 反应应用程序

让我们通过以下命令将 create-react-app 与模板打字稿一起使用

λ npx create-react-app myapp --template typescript

在此处查看链接

请注意,我们不能在项目名称中使用大写字母。

Cannot create a project named "MyApp" because of npm naming restrictions:

* name can no longer contain capital letters

Please choose a different project name

我们得到以下步骤

image.png

image.png

image.png

image.png

最后我们得到以下指令:

image.png

image.png

让我们按照这个:

We suggest that you begin by typing:

cd myapp
npm start

启动后,浏览器会自动打开,我们看到

image.png

image.png

现在我们有了非常基本但功能强大的 typescript react 应用程序,我们将继续为我们的应用程序配置 Keycloak。

3\。为我们的应用程序配置客户端有效重定向 URI 和 Web 源

我们的应用程序运行在:localhost:3000

因此我们将这样设置

image.png

“有效重定向 URI”告诉 keycloak 在登录成功或注销后接受重定向目标。这里localhost:3000/*表示 keycloak 可以接受重定向到以localhost:3000开头的任何 URI,例如localhost:3000/home。

Web Origins:用于 CORS。

此选项以 CORS 为中心,代表跨域资源共享。如果浏览器 JavaScript 尝试向域与 JavaScript 代码所在域不同的服务器发出 AJAX HTTP 请求,则该请求必须使用 CORS。服务器必须以特殊的方式处理 CORS 请求,否则浏览器将不会显示或不允许处理请求。该协议的存在是为了防止 XSS、CSRF 和其他基于 JavaScript 的攻击。

重要提示:Keycloak 支持经过验证的 CORS 请求。它的工作方式是客户端的 Web Origins 设置中列出的域嵌入在发送到客户端应用程序的访问令牌中。然后,客户端应用程序可以使用此信息来决定是否允许在其上调用 CORS 请求。这是 OIDC 协议的扩展,因此只有 Keycloak 客户端适配器支持此功能。

这里我们只是放了我们应用程序的 URI。

最后我们点击“保存”

4\。配置客户端用户和角色

现在我们需要为客户端(我们的应用程序 MyApp)添加用户和角色。

首先单击“用户”部分,同时确保领域是“MyRealm”

image.png

我们得到以下页面

image.png

image.png

首先,我们通过提供登录名“MyUser”来创建一个用户,例如:

image.png

image.png

我们收到以下确认消息

image.png

现在让我们为用户创建一个密码。

点击“凭证”

image.png

我们得到表格:

image.png

我们设置密码并禁用“临时”,然后单击“设置密码”按钮。

我们得到以下确认弹出窗口

image.png

点击“设置密码”按钮

我们得到以下确认

image.png

现在让我们为我们的应用程序添加角色。但首先我们必须意识到,在 Keycloak 中有两种角色:

  • 全局角色

  • 客户端角色

我们将向我们的应用程序添加角色,但使用客户端角色。

为了获得客户角色,我们点击“客户”,然后点击我们的应用程序“MyApp”

image.png

然后我们点击标签“角色”

image.png

我们添加一个新角色

image.png

image.png

image.png

image.png

我们刚刚添加了一个名为“Admin”的角色。它可以是你想要的任何角色。它仅用于演示。

让角色“Admin”链接到我们的用户“myuser”

点击“用户”

image.png

找回我们的用户

image.png

然后单击“编辑”,然后单击“角色映射”

image.png

image.png

然后我们点击组合框“客户端角色”

image.png

然后我们选择我们的应用程序“MyApp”作为客户端:

image.png

我们可以看到我们应用的角色列表,这里只有一个“Admin”

image.png

我们选择角色“Admin”并点击“Add selected”将角色添加到当前用户“Myuser”

image.png

现在我们可以检查用户的有效角色是管理员。当然,我们可以为一个当前用户添加多个角色。

我们现在完成了对 Keycloak 的管理。

我们先确认用户账号没问题,让我们登录账号。

image.png

我们在链接http://localhost:8080/realms/MyRealm/account/#/上得到以下页面

image.png

我们继续“登录”

image.png

image.png

我们使用用户登录名/密码登录

image.png

我们现在确定用户可以使用她的登录名/密码登录。

现在让我们看看如何使用 OpenID Connect 协议来验证和授权想要访问我们客户端 MyApp 的用户

一旦 KeyCloak 使用 OpenId Connect 协议为客户端验证了用户身份,它就会返回两个令牌作为响应:

  • 访问令牌

  • 身份令牌

为此,我们将使用带有 insomia 的 Keycloak 的 api 来测试并获取这两个令牌。

5\。使用用户名和密码通过 API 客户端 Insomia 通过 Keycloak API 对用户进行身份验证和授权

查看链接使用用户名和密码进行身份验证

我们要发送以下 HTTP 请求

curl -d "client_id=admin-cli" -d "username=admin" -d "password=password" -d "grant_type=password" "http://localhost:8080/realms/MyRealm/protocol/openid-connect/token"

我们将使用失眠

zwz 100263 失眠 zwz 100264 zwz 100262

它是一个非常好的测试我们的 api 的应用程序,但在这里我们将使用它通过它的 API 与 Keycloak 服务器进行通信。

我们使用 Insomnia 的精简 API 客户端。

首先我们需要创建一个项目。

image.png

image.png

我们拿回仪表板

image.png

现在我们需要添加我们称之为“docker”的环境,因为 Keycloak 在 docker 上运行。

在选项卡中单击

image.png

然后我们将添加环境“docker”

image.png

在那里,我们设置了环境的所有值,例如我们的 keycloak 服务器的 url、我们的领域、我们的协议。

我们需要在请求中提供更多信息,稍后将在 POST HTTP 请求中提供它们。

{
    "url": "localhost:8080",
    "realm": "MyRealm",
    "protocol": "openid-connect"
}

我们得到这个然后我们点击“完成”

image.png

完成后,请确保使用我们刚刚创建的“docker”环境。

image.png

然后我们在我们的 Keycloak 项目中创建一个新的请求来获取令牌。

image.png

image.png

我们选择 HTTP 方法 POST:

image.png

我们选择如何在 HTTP Post 中传递数据:Form Url Encoded

image.png

image.png

最后点击“创建”

image.png

我们得到以下页面:

image.png

现在让我们提供我们的 keycloak url:

首先我们得到 Scheme : http,然后我们使用 url

我们输入“http://”,然后输入字母“u”作为 url 我们得到

image.png

_url 是在我们的“docker”环境中定义的,记住。

我们点击 _url 然后我们得到

image.png

URI路径后必须是

/realms/[MyRealm]/protocol/openid-connect/token

让我们写

image.png

然后当我们输入字母“r”时,我们选择 _.realm

image.png

我们得到

image.png

然后我们写

image.png

让我们尝试点击“发送”

我们得到

image.png

Keycloak 服务器返回:

  • HTTP 400 错误请求

  • 错误信息“invalid_request”,描述为“Missing form parameter: grant_type”

基本上我们需要发送表单参数grand_type。

有不同的流量

  • 授权码流:用于web app、native app

  • 设备流程:无浏览器和受限输入设备**- 密码流程:仅适用于第一方应用程序**

  • Refresh Token Flow: new Access Token过期时

我们将在这里使用密码流来获取我们应用程序的访问令牌。

https://serving.net/a/granttypes/password/

https://out0.com/dx/gastreatment/applications/application-grant-types

https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.3

1.3.3。资源所有者密码凭证

资源所有者密码凭证(即用户名和密码)可以直接用作授权授予来获取访问令牌。仅当资源所有者和客户端之间存在高度信任时(例如,客户端是设备操作系统或高特权应用程序的一部分)以及其他授权授予类型不可用时,才应使用凭据(例如授权码)。

尽管此授权类型需要直接客户端访问资源所有者凭证,但资源所有者凭证用于单个请求并交换访问令牌。这种授权类型可以消除客户端存储资源所有者凭据以供将来使用的需要,方法是使用长期访问令牌或刷新令牌交换凭据。

因此,让我们通过发送:grant_typeu003dpassword 来使用此密码流程,并在 HTTP 发布请求中设置客户端 ID、登录名和密码。

首先让我们添加“grant\type”参数:

image.png

我们发送请求,我们得到另一个错误

image.png

错误是

{
    "error": "invalid_client",
    "error_description": "Invalid client credentials"
}

我们取得了进展,我们需要客户 ID。让我们添加它:

image.png

我们收到以下错误:

{
     "error": "invalid_request",
     "error_description": "Missing parameter: username"
}

让我们添加用户名和密码

image.png

当我们发送时,我们会得到令牌:访问和刷新令牌!

image.png

image.png

我们刚刚展示了公共客户端如何通过发送登录名/密码来获取访问令牌。

现在我们需要了解更多关于 Access Token 结构的信息。

请记住,我们使用从 OAuth 2.0 派生的协议 Open Connect Id。

访问令牌在此处描述

https://auth0.com/docs/secure/tokens/access-tokens

据说:

Auth0 使用符合 JSON 结构和标准声明的自包含 JSON Web 令牌 (JWT) 访问令牌

让我们检查一下 JWT 网站:

请到https://jwt.io/

当我们粘贴我们的访问令牌时,我们得到:

image.png

我们可以检查访问令牌是否确实在自签名 JWT 中。

有三个部分。

  • JOSE Header:包含关于令牌类型和用于保护其内容的加密算法的元数据。 (红色)

  • JWS 有效负载(声明集):包含可验证的安全声明,例如用户的身份和允许的权限。 (紫色)

  • JWS签名:用于验证token是否可信且未被篡改。当您使用 JWT 时,您必须在存储和使用它之前检查它的签名。 (浅蓝色)

请在此处找到详细信息

让我们使用声明检查有效负载的内容。

{
  "exp": 1653341403,
  "iat": 1653341103,
  "jti": "ec172aa1-a9c1-41d6-8759-baa9469ede34",
  "iss": "http://localhost:8080/realms/MyRealm",
  "aud": "account",
  "sub": "8b5a7866-e968-4b20-9001-5ff5af75fdce",
  "typ": "Bearer",
  "azp": "MyApp",
  "session_state": "40068981-045a-4d5c-bb42-6bbc87d3fe8b",
  "acr": "1",
  "realm_access": {
    "roles": [
      "default-roles-myrealm",
      "offline_access",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "MyApp": {
      "roles": [
        "Admin"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "profile email",
  "sid": "40068981-045a-4d5c-bb42-6bbc87d3fe8b",
  "email_verified": false,
  "preferred_username": "myuser"
}

令牌不包含关于用户的任何信息,除了用户 ID(位于 sub 声明中)。在许多情况下,您可能会发现检索其他用户信息很有用。您可以通过使用访问令牌调用 userinfo API 端点来执行此操作。确保为其颁发访问令牌的 API 使用 RS256 签名算法。

我们可以找到关于结构的文档:

https://out0.com/dx/sugar/tweaks/access-tokens

在我们的例子中,我们将对用户在您的应用程序 MyApp 中的角色感兴趣:

 "resource_access": {
    "MyApp": {
      "roles": [
        "Admin"
      ]
    }

我们可以检查是否设置了“管理员”角色。

第 1 部分到此结束。在接下来的第 2 部分中,我们将向您展示如何在我们的应用程序 React 中使用 Open Connect Id/OAuth 2.0 来增加安全性。

参考

https://developers.redhat.com/blog/2020/11/24/authentication-and-authorization-using-the-keycloak-rest-api#keycloak_connection_using_a_java_application

https://www.keycloak.org/docs-api/18.0/javadocs/index.html

https://openid.net/specs/openid-connect-core-1_0.html#IDToken

https://auth0.com/docs/

https://usmanshahid.medium.com/levels-of-access-control-through-keycloak-part-1-d29e24b0ddad

https://osmanshahd.support.com/levels-of-access-control-through-keycloak-part-2-authentication-flows-8ac3591984

https://usmanshahid.medium.com/levels-of-access-control-through-keycloak-part-3-access-control-through-roles-and-tokens-a1744c04895e

https://usmanshahid.medium.com/levels-of-access-control-through-keycloak-part-3a-integration-with-kubernetes-2568ad2055d4

Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐