Spring Boot 和 OAuth2

本指南将向您展示如何使用 OAuth 2.0Spring Boot 构建一个执行各种“社交登录”功能的示例应用程序。

它从一个简单的、单提供商的单点登录开始,逐步发展到一个可以选择认证提供商的客户端:GitHubGoogle

这些示例都是使用后端 Spring Boot 和 Spring Security 的单页面应用程序。它们的前端也都使用了纯粹的 jQuery。但是,转换为不同的 JavaScript 框架或使用服务器端渲染所需的更改将是微乎其微的。

所有示例都使用了 Spring Boot 中原生的 OAuth 2.0 支持实现。

有几个相互构建的示例,每一步都添加了新功能

  • simple:一个非常基础的静态应用,只有一个主页,通过 Spring Boot 的 OAuth 2.0 配置属性实现无条件登录(如果您访问主页,您将被自动重定向到 GitHub)。

  • click:添加一个用户必须点击才能登录的显式链接。

  • logout:也为已认证用户添加了注销链接。

  • two-providers:添加了第二个登录提供商,以便用户可以在主页上选择使用哪个提供商。

  • custom-error:为未认证用户添加错误消息,并基于 GitHub API 添加自定义认证。

从一个应用迁移到下一个更高功能的应用所需的更改可以在源代码中跟踪。每个版本的应用程序都有自己的目录,以便您可以比较它们的差异。

每个应用都可以导入到 IDE 中。您可以在 SocialApplication 中运行 main 方法来启动应用。它们都会在 http://localhost:8080 上显示主页(并且如果您想登录并查看内容,所有应用都需要您至少拥有 GitHub 和 Google 帐户)。

您也可以使用命令行运行所有应用,通过 mvn spring-boot:run,或者构建 jar 文件后使用 mvn packagejava -jar target/*.jar 运行(根据 Spring Boot 文档 和其他可用文档)。如果您使用顶层目录中的 wrapper,则无需安装 Maven,例如:

$ cd simple
$ ../mvnw package
$ java -jar target/*.jar
这些应用都能在 localhost:8080 上运行,因为它们将使用在该地址注册的 GitHub 和 Google OAuth 2.0 客户端。要在不同的主机或端口上运行它们,您需要以那种方式注册您的应用。如果您使用默认值,则不会有凭据泄露到 localhost 以外的风险。但是,请注意您在互联网上暴露的内容,并且不要将您自己的应用注册信息放入公共源代码控制中。

使用 GitHub 进行单点登录

在本节中,您将创建一个使用 GitHub 进行认证的最小应用程序。利用 Spring Boot 中的自动配置特性,这将非常容易。

创建新项目

首先,您需要创建一个 Spring Boot 应用程序,这可以通过多种方式完成。最简单的方法是访问 https://start.spring.io 并生成一个空项目(选择 "Web" 依赖作为起点)。或者,在命令行上执行此操作:

$ mkdir ui && cd ui
$ curl https://start.spring.io/starter.tgz -d style=web -d name=simple | tar -xzvf -

然后您可以将该项目导入到您喜欢的 IDE 中(默认情况下它是一个普通的 Maven Java 项目),或者只使用文件和命令行上的 mvn 进行工作。

添加主页

在您的新项目中,在 src/main/resources/static 文件夹中创建 index.html。您应该添加一些样式表和 JavaScript 链接,以便结果看起来像这样:

index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>Demo</title>
    <meta name="description" content=""/>
    <meta name="viewport" content="width=device-width"/>
    <base href="/"/>
    <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
    <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
    <script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
	<h1>Demo</h1>
	<div class="container"></div>
</body>
</html>

这些对于演示 OAuth 2.0 登录功能都不是必需的,但最终拥有一个令人愉悦的用户界面会更好,所以您不妨从主页上的一些基本内容开始。

如果您启动应用程序并加载主页,您会注意到样式表没有加载。因此,您还需要通过添加 jQuery 和 Twitter Bootstrap 来添加它们:

pom.xml
<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>jquery</artifactId>
	<version>3.4.1</version>
</dependency>
<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>bootstrap</artifactId>
	<version>4.3.1</version>
</dependency>
<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>webjars-locator-core</artifactId>
</dependency>

最后一个依赖是 webjars 的“定位器”,它由 webjars 网站提供作为一个库。Spring 可以使用定位器来定位 webjars 中的静态资源,而无需知道确切的版本(因此 index.html 中使用了不带版本的 /webjars/** 链接)。只要您不关闭 MVC 自动配置,webjar 定位器在 Spring Boot 应用中是默认激活的。

完成这些更改后,您的应用应该有一个漂亮的首页。

使用 GitHub 和 Spring Security 保护应用程序

为了使应用程序安全,您只需添加 Spring Security 作为依赖。由于您希望进行“社交”登录(委托给 GitHub),您应该包含 Spring Security OAuth 2.0 客户端启动器:

pom.xml
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

添加它后,您的应用将默认使用 OAuth 2.0 进行安全保护。

接下来,您需要配置您的应用以使用 GitHub 作为认证提供商。为此,请执行以下操作:

添加新的 GitHub 应用

要使用 GitHub 的 OAuth 2.0 认证系统进行登录,您必须首先添加一个新的 GitHub 应用

选择“New OAuth App”,然后会显示“Register a new OAuth application”页面。输入应用名称和描述。然后,输入您的应用主页,在本例中应为 http://localhost:8080。最后,将授权回调 URL 指定为 http://localhost:8080/login/oauth2/code/github,然后点击 Register Application

OAuth 重定向 URI 是用户代理在通过 GitHub 进行认证并在授权应用程序页面上授予应用程序访问权限后,重定向回应用程序的路径。

默认的重定向 URI 模板是 {baseUrl}/login/oauth2/code/{registrationId}registrationIdClientRegistration 的唯一标识符。

配置 application.yml

然后,为了建立与 GitHub 的链接,将以下内容添加到您的 application.yml 中:

application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            clientId: github-client-id
            clientSecret: github-client-secret
# ...

只需使用您刚刚在 GitHub 创建的 OAuth 2.0 凭据,将 github-client-id 替换为客户端 ID,将 github-client-secret 替换为客户端密钥。

启动应用程序

进行此更改后,您可以再次运行您的应用程序并访问 http://localhost:8080 上的主页。现在,您应该被重定向到 GitHub 进行登录,而不是直接看到主页。如果您执行此操作并接受被要求进行的任何授权,您将被重定向回本地应用程序,并且主页将可见。

如果您保持登录到 GitHub,即使您在一个没有 cookie 和没有缓存数据的全新浏览器中打开此本地应用,您也无需重新认证。(这就是单点登录的含义。)

如果您正在使用示例应用程序完成本节,请务必清除浏览器缓存中的 cookie 和 HTTP Basic 凭据。对于单个服务器来说,最好的方法是打开一个新的隐私窗口。

授予此示例应用程序访问权限是安全的,因为只有在本地运行的应用才能使用这些令牌,并且其请求的范围是有限的。但是,当您登录到此类应用时,请注意您批准的内容:它们可能会请求您不愿授予的权限(例如,它们可能会请求更改您的个人数据的权限,这可能不符合您的利益)。

刚才发生了什么?

您刚才编写的应用,用 OAuth 2.0 的术语来说,是一个客户端应用程序,它使用授权码授权从 GitHub(授权服务器)获取访问令牌。

然后它使用访问令牌向 GitHub 请求一些个人详细信息(仅限您允许的操作),包括您的登录 ID 和姓名。在此阶段,GitHub 充当资源服务器,解码您发送的令牌并检查它是否赋予应用程序访问用户详细信息的权限。如果该过程成功,应用程序会将用户详细信息插入到 Spring Security 上下文中,以便您获得认证。

如果您在浏览器工具(Chrome 或 Firefox 中按 F12)中查看并跟踪所有跳转的网络流量,您将看到与 GitHub 之间的来回重定向,最终您将回到主页并带有新的 Set-Cookie 头部。此 cookie(默认为 JSESSIONID)是您在 Spring(或任何基于 Servlet 的)应用程序中认证详细信息的令牌。

因此,我们拥有一个安全的应用程序,其意义在于用户必须通过外部提供商(GitHub)进行认证才能查看任何内容。

我们不会想将此用于网上银行网站。但对于基本身份识别以及区分您网站不同用户的内容,它是一个很好的起点。这就是为什么这种类型的认证现在非常流行。

在下一节中,我们将为应用程序添加一些基本功能。我们还将使用户在首次重定向到 GitHub 时更加清楚正在发生的事情。

添加欢迎页面

在本节中,您将通过添加一个显式链接来修改您刚刚构建的 simple 应用,该链接用于使用 GitHub 登录。新链接将显示在主页上,而不是立即重定向,用户可以选择登录或保持未认证状态。只有当用户点击该链接后,安全内容才会呈现。

主页上的条件内容

要根据用户是否认证来渲染内容,您可以选择服务器端或客户端渲染。

在这里,您将使用 JQuery 修改客户端代码,不过如果您更喜欢使用其他工具,转换客户端代码应该不会太难。

要开始使用动态内容,您需要像这样标记几个 HTML 元素:

index.html
<div class="container unauthenticated">
    With GitHub: <a href="/oauth2/authorization/github">click here</a>
</div>
<div class="container authenticated" style="display:none">
    Logged in as: <span id="user"></span>
</div>

默认情况下,第一个 <div> 会显示,第二个不会。请注意,带 id 属性的空 <span> 也需要注意。

稍后,您将添加一个服务器端端点,该端点将以 JSON 格式返回已登录用户的详细信息。

但是,首先添加以下 JavaScript,它将调用该端点。根据端点的响应,此 JavaScript 将使用用户的姓名填充 <span> 标签,并适当地切换 <div> 的显示状态:

index.html
<script type="text/javascript">
    $.get("/user", function(data) {
        $("#user").html(data.name);
        $(".unauthenticated").hide()
        $(".authenticated").show()
    });
</script>

注意,此 JavaScript 期望服务器端端点名为 /user

/user 端点

现在,您将添加刚刚提到的服务器端端点,并将其命名为 /user。它将返回当前已登录的用户,这在我们主类中可以很轻松地实现:

SocialApplication.java
@SpringBootApplication
@RestController
public class SocialApplication {

    @GetMapping("/user")
    public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
        return Collections.singletonMap("name", principal.getAttribute("name"));
    }

    public static void main(String[] args) {
        SpringApplication.run(SocialApplication.class, args);
    }

}

请注意使用了 @RestController@GetMapping 以及注入到处理方法中的 OAuth2User

在端点中返回完整的 OAuth2User 不是一个好主意,因为它可能包含您不愿向浏览器客户端透露的信息。

使主页公开访问

您还需要进行最后一项更改。

现在,这个应用将正常工作并像以前一样进行认证,但在显示页面之前仍然会发生重定向。为了使链接可见,我们还需要通过继承 WebSecurityConfigurerAdapter 来关闭主页上的安全控制:

SocialApplication
@SpringBootApplication
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {

    // ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	// @formatter:off
        http
            .authorizeRequests(a -> a
                .antMatchers("/", "/error", "/webjars/**").permitAll()
                .anyRequest().authenticated()
            )
            .exceptionHandling(e -> e
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
            )
            .oauth2Login();
        // @formatter:on
    }

}

Spring Boot 为使用 @SpringBootApplication 注解的类上的 WebSecurityConfigurerAdapter 赋予了特殊含义:它使用它来配置承载 OAuth 2.0 认证处理器的安全过滤器链。

以上配置指示了允许访问的端点白名单,所有其他端点都需要认证。

您想允许

  • /,因为这是您刚刚设置为动态的页面,其中一些内容对未认证用户可见

  • /error,因为这是 Spring Boot 用于显示错误的端点,以及

  • /webjars/**,因为您希望您的 JavaScript 对所有访问者(无论是否认证)都运行

不过,您在此配置中不会看到关于 /user 的任何内容。所有端点,包括 /user,都保持安全,除非明确指定,因为末尾有 .anyRequest().authenticated() 配置。

最后,由于我们通过 Ajax 与后端交互,我们希望配置端点响应 401 状态码,而不是默认的重定向到登录页面的行为。配置 authenticationEntryPoint 可以为我们实现这一点。

完成这些更改后,应用程序就完成了。如果您运行它并访问主页,您应该会看到一个样式精美的 HTML 链接“使用 GitHub 登录”。此链接不会直接将您带到 GitHub,而是带到处理认证的本地路径(并发送一个重定向到 GitHub)。认证成功后,您会被重定向回本地应用,此时它会显示您的姓名(假设您在 GitHub 中设置了权限以允许访问该数据)。

添加注销按钮

在本节中,我们将修改之前构建的 click 应用,添加一个允许用户注销应用程序的按钮。这似乎是一个简单的功能,但实现起来需要一些注意,因此值得花一些时间来讨论具体如何实现。大多数更改与我们将应用程序从只读资源转换为读写资源(注销需要更改状态)的事实有关,因此任何非静态内容的实际应用程序都需要进行相同的更改。

客户端更改

在客户端,我们只需要提供一个注销按钮和一些 JavaScript 来调用服务器取消认证。首先,在 UI 的“已认证”部分,我们添加按钮:

index.html
<div class="container authenticated">
  Logged in as: <span id="user"></span>
  <div>
    <button onClick="logout()" class="btn btn-primary">Logout</button>
  </div>
</div>

然后我们在 JavaScript 中提供它引用的 logout() 函数:

index.html
var logout = function() {
    $.post("/logout", function() {
        $("#user").html('');
        $(".unauthenticated").show();
        $(".authenticated").hide();
    })
    return true;
}

logout() 函数向 /logout 发送一个 POST 请求,然后清除动态内容。现在我们可以切换到服务器端来实现该端点。

添加注销端点

Spring Security 内置支持 /logout 端点,它会为我们做正确的事情(清除会话并使 cookie 失效)。要配置此端点,我们只需扩展 WebSecurityConfigurerAdapter 中现有的 configure() 方法:

SocialApplication.java
@Override
protected void configure(HttpSecurity http) throws Exception {
	// @formatter:off
    http
        // ... existing code here
        .logout(l -> l
            .logoutSuccessUrl("/").permitAll()
        )
        // ... existing code here
    // @formatter:on
}

/logout 端点要求我们向其发送 POST 请求,并且为了保护用户免受跨站请求伪造 (CSRF,发音为 "sea surf") 的攻击,它要求请求中包含一个令牌。令牌的值与当前会话关联,这提供了保护,因此我们需要一种方法将该数据获取到我们的 JavaScript 应用中。

许多 JavaScript 框架内置了对 CSRF 的支持(例如在 Angular 中他们称之为 XSRF),但其实现方式通常与 Spring Security 的开箱即用行为略有不同。例如,在 Angular 中,前端希望服务器发送一个名为“XSRF-TOKEN”的 cookie,如果看到这个 cookie,它会将该值作为名为“X-XSRF-TOKEN”的头部发送回去。我们可以使用简单的 jQuery 客户端实现相同的行为,这样服务器端的更改就可以与其他的许多前端实现兼容,只需很少甚至无需更改。为了让 Spring Security 了解这一点,我们需要添加一个创建 cookie 的过滤器。

WebSecurityConfigurerAdapter 中,我们执行以下操作:

SocialApplication.java
@Override
protected void configure(HttpSecurity http) throws Exception {
	// @formatter:off
    http
        // ... existing code here
        .csrf(c -> c
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        )
        // ... existing code here
    // @formatter:on
}

在客户端添加 CSRF 令牌

由于在此示例中我们不使用更高级别的框架,您需要显式添加 CSRF 令牌,该令牌已从后端作为 cookie 提供。为了使代码更简单一些,请包含 js-cookie 库:

pom.xml
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>js-cookie</artifactId>
    <version>2.1.0</version>
</dependency>

然后,您可以在 HTML 中引用它:

index.html
<script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>

最后,您可以在 XHR 中使用 Cookies 的便捷方法:

index.html
$.ajaxSetup({
  beforeSend : function(xhr, settings) {
    if (settings.type == 'POST' || settings.type == 'PUT'
        || settings.type == 'DELETE') {
      if (!(/^http:.*/.test(settings.url) || /^https:.*/
        .test(settings.url))) {
        // Only send the token to relative URLs i.e. locally.
        xhr.setRequestHeader("X-XSRF-TOKEN",
          Cookies.get('XSRF-TOKEN'));
      }
    }
  }
});

准备就绪!

完成这些更改后,我们就可以运行应用程序并尝试新的注销按钮了。启动应用程序并在新的浏览器窗口中加载主页。点击“登录”链接前往 GitHub(如果您已在那里登录,您可能不会注意到重定向)。点击“注销”按钮取消当前会话,并将应用程序返回到未认证状态。如果您好奇,您应该可以在浏览器与本地服务器交换的请求中看到新的 cookie 和头部信息。

请记住,现在注销端点可以与浏览器客户端正常工作,那么所有其他 HTTP 请求(POST、PUT、DELETE 等)也将同样正常工作。因此,这应该是一个带有更现实功能的应用程序的良好平台。

使用 GitHub 登录

在本节中,您将修改已经构建的 logout 应用,添加一个选择页面,以便终端用户可以在多个凭证集合之间进行选择。

让我们添加 Google 作为终端用户的第二个选择。

初步设置

要使用 Google 的 OAuth 2.0 认证系统进行登录,您必须在 Google API 控制台中设置一个项目以获取 OAuth 2.0 凭据。

请遵循 OpenID Connect 页面上的说明,从“设置 OAuth 2.0”部分开始。

完成“获取 OAuth 2.0 凭据”的说明后,您应该拥有一个新的 OAuth 客户端,其凭据包括客户端 ID 和客户端密钥。

设置重定向 URI

此外,您还需要提供一个重定向 URI,就像您之前为 GitHub 所做的那样。

在“设置重定向 URI”子部分中,确保授权重定向 URI 字段设置为 http://localhost:8080/login/oauth2/code/google

添加客户端注册

然后,您需要配置客户端指向 Google。因为 Spring Security 在设计时考虑了多个客户端,您可以将我们的 Google 凭据与您为 GitHub 创建的凭据一起添加:

application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            clientId: github-client-id
            clientSecret: github-client-secret
          google:
            client-id: google-client-id
            client-secret: google-client-secret

如您所见,Google 是 Spring Security 开箱即用支持的另一个提供商。

在客户端,更改非常简单 - 您只需添加另一个链接:

index.html
<div class="container unauthenticated">
  <div>
    With GitHub: <a href="/oauth2/authorization/github">click here</a>
  </div>
  <div>
    With Google: <a href="/oauth2/authorization/google">click here</a>
  </div>
</div>
URL 中的最终路径应与 application.yml 中的客户端注册 ID 匹配。
Spring Security 提供了一个默认的提供商选择页面,可以通过指向 /login 而不是 /oauth2/authorization/{registrationId} 来访问。

如何添加本地用户数据库

许多应用程序需要本地存储关于用户的数据,即使认证委托给了外部提供商。这里不展示代码,但通过两个步骤很容易实现。

  1. 为您的数据库选择一个后端,并为适合您需求且可以从外部认证完全或部分填充的自定义 User 对象设置一些存储库(例如使用 Spring Data)。

  2. 实现并暴露 OAuth2UserService 以调用授权服务器和您的数据库。您的实现可以委托给默认实现,它将完成调用授权服务器的繁重工作。您的实现应返回一个扩展您的自定义 User 对象并实现 OAuth2User 的内容。

提示:在 User 对象中添加一个字段,用于链接到外部提供商中的唯一标识符(不是用户名,而是外部提供商中帐户的唯一标识符)。

为未认证用户添加错误页面

在本节中,您将修改之前构建的 two-providers 应用,以便为无法认证的用户提供反馈。同时,您将扩展认证逻辑,增加一个规则,仅允许属于特定 GitHub 组织的用户进行认证。“组织”是 GitHub 领域特定的概念,但对于其他提供商也可以设计类似的规则。例如,使用 Google 时,您可能只想认证来自特定域的用户。

切换到 GitHub

two-providers 示例使用 GitHub 作为 OAuth 2.0 提供商。

application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: bd1c0a783ccdd1c9b9e4
            client-secret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
          # ...

在客户端检测认证失败

在客户端,您可能希望为无法认证的用户提供一些反馈。为了方便实现这一点,您可以添加一个 div 元素,最终将在此元素中添加信息性消息。

index.html
<div class="container text-danger error"></div>

然后,添加对 /error 端点的调用,用结果填充 <div>

index.html
$.get("/error", function(data) {
    if (data) {
        $(".error").html(data);
    } else {
        $(".error").html('');
    }
});

error 函数向后端检查是否有要显示的错误:

添加错误消息

为了支持获取错误消息,您需要在认证失败时捕获它。为了实现这一点,您可以配置一个 AuthenticationFailureHandler,如下所示:

protected void configure(HttpSecurity http) throws Exception {
	// @formatter:off
	http
	    // ... existing configuration
	    .oauth2Login(o -> o
            .failureHandler((request, response, exception) -> {
			    request.getSession().setAttribute("error.message", exception.getMessage());
			    handler.onAuthenticationFailure(request, response, exception);
            })
        );
}

上述配置会在认证失败时将错误消息保存到会话中。

然后,您可以添加一个简单的 /error 控制器,如下所示:

SocialApplication.java
@GetMapping("/error")
public String error(HttpServletRequest request) {
	String message = (String) request.getSession().getAttribute("error.message");
	request.getSession().removeAttribute("error.message");
	return message;
}
这将替换应用程序中默认的 /error 页面,这对于我们的情况来说没问题,但可能无法满足您的复杂需求。

在服务器端生成 401

如果用户无法或不想使用 GitHub 登录,Spring Security 已经会返回 401 响应,因此如果您认证失败(例如,拒绝令牌授权),应用程序已经可以正常工作。

为了增加一些趣味性,您可以扩展认证规则,拒绝不在正确组织中的用户。

您可以使用 GitHub API 了解更多关于用户的信息,因此您只需将其插入到认证过程的正确部分。

幸运的是,对于如此简单的用例,Spring Boot 提供了一个易于使用的扩展点:如果您声明一个类型为 OAuth2UserService@Bean,它将用于识别用户主体。您可以使用这个钩子来断言用户在正确的组织中,否则抛出异常:

SocialApplication.java
@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService(WebClient rest) {
    DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
    return request -> {
        OAuth2User user = delegate.loadUser(request);
        if (!"github".equals(request.getClientRegistration().getRegistrationId())) {
        	return user;
        }

        OAuth2AuthorizedClient client = new OAuth2AuthorizedClient
                (request.getClientRegistration(), user.getName(), request.getAccessToken());
        String url = user.getAttribute("organizations_url");
        List<Map<String, Object>> orgs = rest
                .get().uri(url)
                .attributes(oauth2AuthorizedClient(client))
                .retrieve()
                .bodyToMono(List.class)
                .block();

        if (orgs.stream().anyMatch(org -> "spring-projects".equals(org.get("login")))) {
            return user;
        }

        throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token", "Not in Spring Team", ""));
    };
}

请注意,此代码依赖于 WebClient 实例,以代表已认证用户访问 GitHub API。完成后,它会遍历组织列表,查找与“spring-projects”匹配的组织(这是用于存储 Spring 开源项目的组织)。如果您想成功认证且不在 Spring Engineering 团队中,您可以替换为您自己的值。如果没有匹配项,它会抛出 OAuth2AuthenticationException,然后 Spring Security 会捕获此异常并将其转换为 401 响应。

WebClient 也必须作为一个 bean 创建,但这很简单,因为使用了 spring-boot-starter-oauth2-client 后,其所有组成部分都可以自动装配:

@Bean
public WebClient rest(ClientRegistrationRepository clients, OAuth2AuthorizedClientRepository authz) {
    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(clients, authz);
    return WebClient.builder()
            .filter(oauth2).build();
}
显然,上面的代码可以推广到其他认证规则,有些适用于 GitHub,有些适用于其他 OAuth 2.0 提供商。您只需要 WebClient 和一些提供商 API 的知识。

结论

我们已经看到了如何使用 Spring Boot 和 Spring Security 以多种风格轻松构建应用程序。贯穿所有示例的主要主题是使用外部 OAuth 2.0 提供商进行认证。

所有示例应用程序都可以轻松扩展和重新配置以适应更具体的用例,通常只需更改配置文件即可。请记住,如果您在自己的服务器中使用这些示例的变体,请在 GitHub(或类似服务)上注册,并获取您自己主机地址的客户端凭据。并记住不要将这些凭据放入源代码控制中!

想编写新的指南或贡献现有的指南?请查阅我们的贡献指南

所有指南的代码都以 ASLv2 许可发布,而文字部分则以 署名-禁止演绎 创意共享许可 发布。

获取代码