Spring Security OAuth 2 教程 - 1:熟悉 OAuth 2 概念

安全是一个需要深入理解的复杂主题。此外,使用 OAuth 2.0OpenID Connect 规范为基于微服务的复杂系统实现认证和授权更加困难。像 Spring Security 这样的框架和库有助于降低复杂性,但要正确实现 Security 仍然需要经历陡峭的学习曲线。

在本 Spring Security OAuth2 系列教程中,我将与大家分享如何使用 Spring Security OAuth2 为基于微服务的应用实现认证和授权。

有许多身份提供商(Identity Provider)解决方案,如 KeycloakOktaAuth0 等。在本系列中,我们将使用开源身份和访问管理解决方案 Keycloak

我不是安全、OAuth2 和 Keycloak 方面的专家。我只是根据自己对这些概念的理解与大家分享我的学习心得。如果你认为其中有任何概念或解释不正确,请指正。

我们不会直接进入 Spring Security OAuth2 的实现,而是先从概念开始学习,循序渐进。

了解 OAuth 2.0 和 OpenID Connect 的基础知识

学习 OAuth 2.0 和 OpenID Connect 的第一步是了解一些核心概念,如 OAuth2 中的各种角色(Role)是什么、各种授权方式(Grant Type)是什么以及何时使用哪种方式。

简而言之,在 OAuth2 系统中,有各种不同的组件扮演着不同的角色,也有不同的方法来验证用户身份。

OAuth2.0 角色(Role)

  • 资源所有者(Resource Owner): 资源所有者通常是终端终用户,他授权应用(客户端)访问他/她的账户。
  • 资源服务器(Resource Server): 托管受保护资源的服务器。这是你要访问的 API。
  • 客户端(Client): 代表资源所有者请求访问受保护资源的应用(资源所有者正在使用的应用)。
  • 授权服务器(Authorization Server): 对资源所有者进行身份验证并在成功授权后发放访问令牌(Access Token)的服务器。

OAuth2.0 授权方式(Grant Type)

  • 授权码模式
  • PKCE 授权码模式
  • 客户端凭证模式
  • 隐式/简化模式(不推荐)
  • 资源所有者密码模式(不推荐)

OAuth 2.0 只涉及授权(Authorization),而不涉及身份认证(Authentication)。OpenID Connect 规范是为解决身份认证问题而制定的,它是 OAuth 2.0 的基础层。

在本系列的后续部分中,我们将进一步了解在何时使用哪种授权方式。

安装 Keycloak

如前所述,我们将使用 Keycloak 来实现基于 OAuth2.0/OpenID Connect 的 Security。

首先使用 docker compose 安装 Keycloak。

version: '3.8'

services:
  keycloak:
    image: quay.io/keycloak/keycloak:22.0.3
    command: ['start-dev']
    container_name: keycloak
    hostname: keycloak
    environment:
      - KEYCLOAK_ADMIN=admin
      - KEYCLOAK_ADMIN_PASSWORD=admin1234
    ports:
      - "9191:8080"

启动 Keycloak 容器,如下:

$ docker compose up -d

我们以开发模式启动了 keycloak 容器,并使用环境变量配置了 admin 用户凭证。容器的 8080 端口映射到主机的 9191 端口。

现在你可以通过 http://localhost:9191 访问 Keycloak 管理控制台。

创建 Realm

摘自 Keycloak 的文档:

一个 Realm 管理一组用户、凭证、角色和组。用户属于并登录到一个 Realm。Realm 之间相互隔离,只能管理和验证其控制的用户。

你可以创建一个新的 Realm,将一组客户端、用户、角色等与其他客户端、用户、角色等隔离开来。

使用 admin/admin1234 登录管理控制台后,左上角有一个下拉菜单,其中提供了创建新 Realm 的选项。

输入 Realm 名称:sivalabs,设置 EnabledOn,然后点击 Create

创建成功后,应自动选择新 Realm。如果没有,请从下拉菜单中选择 sivalabs Realm。

创建客户端

要创建新客户端,请点击左侧导航菜单上的 Clients,然后点击 Create client 按钮。

  • General Settings
    • Client type:OpenID Connect
    • Client ID:messages-webapp
  • Capability config
    • Client authentication:On
    • Authorization:Off
    • Authentication flow:选中 Standard flow,取消选中其余复选框
  • Login settings
    • Root URLhttp://localhost:8080
    • Home URLhttp://localhost:8080
    • Valid redirect URIs: http://localhost:8080/callback
    • Valid post logout redirect URIshttp://localhost:8080
    • Web originshttp://localhost:8080

使用上述配置创建客户端后,你将进入新创建的客户端 “Settings” 页面。单击 “Credentials” 选项卡并复制 “Client secret” 值。

在本例中,“Client secret” 是:qVcg0foCUNyYbgF0Sg52zeIhLYyOwXpQ.

Keycloak Client AccessType

如果你使用过 Keycloak 的早期版本,你可能会知道有一个名为 AccessType 的选项,其可能的值为 publicconfidentialbearer-only。在新版本中,没有明确的 AccessType 字段。

  • 如果 Client authenticationOff,则是公共(public)客户端。
  • 如果 Client authenticationOn,则是保密(confidential)客户端。
  • 如果 Client authenticationOn,但是未启用任何 Authentication flow 选项,那么是 Bearer-only 客户端。

现在你可能会问,什么是公开客户端、保密客户端和 Bearer-only 客户端?

  • 公共客户端是面向用户的应用,没有服务器后台,如单页应用。它们不能安全地存储任何敏感数据,如 Client secret。
  • 保密客户端是在后端服务器上运行的 Web 应用,如 Spring MVC 应用。它们可以安全地存储 Client secret 等敏感数据。
  • Bearer-only 客户端通常是仅后台应用(API),它需要调用者提供 access_token。如果调用者没有提供有效的 access_token,它就会简单地返回 Unauthorized(未授权)响应,而不会启动身份认证流程。

创建用户(User)

现在,让我们创建一个用户。点击左侧导航菜单上的 “Users”,然后点击 “Add user” 按钮。

创建一个具有以下详细信息的用户:

  • Username:siva
  • Emailsiva@gmail.com
  • Email verified:Yes
  • First name:Siva
  • Last name:Katamreddy

创建用户后,转到 “Credentials” 选项卡,将 “Password” 设置为 siva1234,“Temporary” 选项设置为 “Off”。

现在你就可以使用 siva 用户的凭证登录到 sivalabs Realm 了。

访问 http://localhost:9191/realms/sivalabs/account/ 并使用 siva/siva1234 登录。

总结

好了,现在我们已经完成了初始设置,可以开始探索 OAuth 2.0 和 OpenID Connect 了。

在下一篇 Spring Security OAuth 2 教程 - 2:授权码模式 文章中,我们将了解如何通过 “授权码模式”(Authorization Code Flow)获取访问令牌(Access Token)。


参考:https://www.sivalabs.in/spring-security-oauth2-tutorial-introduction/