保护 ASP.NET Core Blazor WebAssemblySecure ASP.NET Core Blazor WebAssembly

本文内容

作者:Javier Calvarro Nelson

重要

Blazor WebAssembly 为预览版状态

ASP.NET Core 3.0 支持 Blazor Server。Blazor WebAssembly 在 ASP.NET Core 3.1 中为预览版。

备注

本文中的指导适用于 ASP.NET Core Blazor WebAssembly 模板 3.2 版或更高版本。要在未使用 Visual Studio 版本 16.6 预览版 2 或更高版本时获取最新的 Blazor WebAssembly 模板(版本 3.2.0-preview3.20168.3),请参阅 ASP.NET Core Blazor 入门

Blazor WebAssembly 应用与单页应用程序 (SPA) 的保护方式相同。可通过多种方式向 SPA 进行用户身份验证,但最常用、最全面的方式是使用基于 oAuth 2.0 协议的实现,例如 Open ID Connect (OIDC)

身份验证库Authentication library

Blazor WebAssembly 支持通过 Microsoft.AspNetCore.Components.WebAssembly.Authentication 库使用 OIDC 对应用进行身份验证和授权。该库提供一组基元,可用于对 ASP.NET Core 后端进行无缝身份验证。该库将 ASP.NET Core 标志与以标识服务器为基础的 API 身份验证集成。该库可以针对支持 OIDC 的任何第三方标识提供者 (IP),即 OpenID 提供者 (OP),进行身份验证。

Blazor WebAssembly 中的身份验证支持建立在 oidc-client.js 库的基础之上,该库用于处理底层身份验证协议详细信息。

还有对 SPA 进行身份验证的其他选项,例如使用 SameSite cookie。但是,Blazor WebAssembly 的工程设计决定,oAuth 和 OIDC 是在 Blazor WebAssembly 应用中进行身份验证的最佳选择。出于以下功能和安全原因,选择了以 JSON Web 令牌 (JWT) 为基础的基于令牌的身份验证而不是基于 cookie 的身份验证

  • 使用基于令牌的协议可以减小攻击面,因为并非所有请求中都会发送令牌。
  • 服务器终结点不要求针对跨站点请求伪造 (CSRF) 进行保护,因为会显式发送令牌。因此,可以将 Blazor WebAssembly 应用与 MVC 或 Razor Pages 应用托管在同一位置。
  • 令牌的权限比 cookie 窄。例如,令牌不能用于管理用户帐户或更改用户密码,除非显式实现了此类功能。
  • 令牌的生命周期更短(默认为一小时),这限制了攻击时间窗口。还可随时撤销令牌。
  • 自包含 JWT 向客户端和服务器提供身份验证进程保证。例如,客户端可以检测和验证它收到的令牌是否合法,以及是否是在给定身份验证过程中发出的。如果有第三方尝试在身份验证进程中偷换令牌,客户端可以检测被偷换的令牌并避免使用它。
  • oAuth 和 OIDC 的令牌不依赖于用户代理行为正确以确保应用安全。
  • 基于令牌的协议(例如 oAuth 和 OIDC)允许用同一组安全特征对托管和独立应用进行验证和授权。

使用 OIDC 的身份验证进程Authentication process with OIDC

Microsoft.AspNetCore.Components.WebAssembly.Authentication 库提供几个基元,用于实现使用 OIDC 的身份验证和授权。从广义上说来,身份验证的原理如下:

  • 当匿名用户选择登录按钮或请求应用了 [Authorize] 特性的页面时,会将其重定向到应用的登录页 (/authentication/login)。
  • 在登录页上,身份验证库准备重定向到授权终结点。授权终结点在 Blazor WebAssembly 应用外部,可托管在独立的源。该终结点负责确定用户是否通过身份验证,并发送一个或更多令牌作为响应。身份验证库提供登录回叫以接收身份验证响应。
    • 如果用户未通过身份验证,会将其重定向到底层身份验证系统,通常是 ASP.NET Core 标识。
    • 如果用户已通过身份验证,则授权终结点会生成相应的令牌,并将浏览器重定向回登录回叫终结点 (/authentication/login-callback)。
  • 当 Blazor WebAssembly 应用加载登录回叫终结点 (/authentication/login-callback) 时,就处理了身份验证进程。
    • 如果身份验证进程成功完成,则用户通过身份验证,可以选择返回该用户请求的原受保护 URL。
    • 如果身份验证进程由于任何原因而失败,会将用户导向登录失败页 (/authentication/login-failed),并显示错误。

用于托管应用和第三方登录提供程序的选项Options for hosted apps and third-party login providers

使用第三方提供程序对托管的 Blazor WebAssembly 应用进行身份验证和授权时,有几个选项可用于对用户进行身份验证。选择哪一种选项取决于方案。

有关详细信息,请参阅 在 ASP.NET Core 中保存外部提供程序的其他声明和令牌

对用户进行身份验证,以仅调用受保护的第三方 APIAuthenticate users to only call protected third party APIs

使用针对第三方 API 提供程序的客户端 oAuth 流对用户进行身份验证:

  1. builder.services.AddOidcAuthentication(options => { ... });

在本方案中:

  • 托管应用的服务器不会发挥作用。
  • 无法保护服务器上的 API。
  • 应用只能调用受保护的第三方 API。

使用第三方提供程序对用户进行身份验证,并在主机服务器和第三方调用受保护的 APIAuthenticate users with a third-party provider and call protected APIs on the host server and the third party

使用第三方登录提供程序配置标识。获取第三方 API 访问所需的令牌并进行存储。

当用户登录时,标识将在身份验证过程中收集访问和刷新令牌。此时,可通过几种方法向第三方 API 进行 API 调用。

使用服务器访问令牌检索第三方访问令牌Use a server access token to retrieve the third-party access token

使用服务器上生成的访问令牌从服务器 API 终结点检索第三方访问令牌。在此处,使用第三方访问令牌直接从客户端上的标识调用第三方 API 资源。

我们不建议使用此方法。此方法需要将第三方访问令牌视为针对公共客户端生成。在 oAuth 范畴,公共应用没有客户端机密,因为不能信任此类应用来安全地存储机密,并且访问令牌是为机密客户端而生成的。机密客户端具有客户端机密,并且假定能够安全地存储机密。

  • 第三方访问令牌可能会被授予其他作用域,以便基于第三方为更受信任的客户端发出令牌的情况执行敏感操作。
  • 同样,不应向不受信任的客户端颁发刷新令牌,因为这样做会给客户端提供无限制的访问权限,除非存在其他限制。

从客户端向服务器 API 发出 API 调用以便调用第三方 APIMake API calls from the client to the server API in order to call third-party APIs

从客户端向服务器 API 发出 API 调用。从服务器中检索第三方 API 资源的访问令牌,并发出任何所需调用。

尽管此方法需要额外的网络跃点通过服务器来调用第三方 API,但最终可提供更安全的体验:

  • 服务器可以存储刷新令牌,并确保应用不会失去对第三方资源的访问权限。
  • 应用无法从服务器泄漏可能包含更多敏感权限的访问令牌。