最小 API 中的身份验证和授权

最小 API 支持 ASP.NET Core 中提供的所有身份验证和授权选项,并提供一些附加功能来改善使用身份验证的体验。

有关身份验证和授权的关键概念

身份验证是确定用户身份的过程。 授权是确定用户是否有权访问资源的过程。 在 ASP.NET Core 中,身份验证和授权方案都有类似的实现语义。 身份验证由身份验证服务 IAuthenticationService 负责,而它供身份验证中间件使用。 授权由授权服务 IAuthorizationService 负责,而它供授权中间件使用。

身份验证服务会使用已注册的身份验证处理程序来完成与身份验证相关的操作。 例如,与身份验证相关的操作是对用户进行身份验证或注销用户。 身份验证方案是用于唯一地标识身份验证处理程序及其配置选项的名称。 身份验证处理程序负责实现身份验证策略,并在给定特定身份验证策略(如 OAuth 或 OIDC)的情况下生成用户的声明。 配置选项也是策略独有的,并为处理程序提供会影响身份验证行为的配置,例如重定向 URI。

在授权层中,有两种策略可用于确定用户对资源的访问权限:

  • 基于角色的策略根据所分配的角色(例如 AdministratorUser)确定用户的访问权限。 有关基于角色的授权的详细信息,请参阅基于角色的授权文档
  • 基于声明的策略根据中央颁发机构颁发的声明来确定用户的访问权限。 有关基于声明的授权的详细信息,请参阅基于声明的授权文档

在 ASP.NET Core 中,这两种策略都被捕获到授权要求中。 授权服务利用授权处理程序来确定特定用户是否满足应用于资源的授权要求。

在最小应用中启用身份验证

若要启用身份验证,请调用 AddAuthentication 以对应用的服务提供商注册所需的身份验证服务。

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

通常情况下,会使用一个特定的身份验证策略。 在以下示例中,应用被配置为支持基于 JWT 持有者的身份验证。 此示例使用 Microsoft.AspNetCore.Authentication.JwtBearer NuGet 包中提供的 API。

var builder = WebApplication.CreateBuilder(args);
// Requires Microsoft.AspNetCore.Authentication.JwtBearer
builder.Services.AddAuthentication().AddJwtBearer();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

默认情况下,如果启用了某些身份验证和授权服务,WebApplication 会自动注册身份验证和授权中间件。 在以下示例中,无需调用 UseAuthenticationUseAuthorization 即可注册中间件,因为在调用 AddAuthenticationAddAuthorization 后,WebApplication 会自动执行此操作。

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

在某些情况(例如控制中间件顺序)下,需要显式注册身份验证和授权。 在以下示例中,身份验证中间件是在 CORS 中间件运行后运行的。 有关中间件和此自动行为的详细信息,请参阅最小 API 应用中的中间件

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

var app = builder.Build();

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/", () => "Hello World!");
app.Run();

配置身份验证策略

身份验证策略通常支持通过选项加载的各种配置。 对于以下身份验证策略,最小应用支持从配置加载选项:

ASP.NET Core 框架应会在配置中的 Authentication:Schemes:{SchemeName} 部分下找到这些选项。 在以下示例中,两个不同的方案 BearerLocalAuthIssuer 是使用各自的选项定义的。 Authentication:DefaultScheme 选项可用于配置所使用的默认身份验证策略。

{
  "Authentication": {
    "DefaultScheme":  "LocalAuthIssuer",
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "https://localhost:7259",
          "http://localhost:5259"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      },
      "LocalAuthIssuer": {
        "ValidAudiences": [
          "https://localhost:7259",
          "http://localhost:5259"
        ],
        "ValidIssuer": "local-auth"
      }
    }
  }
}

Program.cs 中,注册了两个基于 JWT 持有者的身份验证策略,其中:

  • “Bearer”方案名称。
  • “LocalAuthIssuer”方案名称。

“Bearer”是支持基于 JWT 持有者的应用中的一个典型默认方案,但可以通过设置 DefaultScheme 属性来替代默认方案,如前面的示例所示。

方案名称用于唯一地标识身份验证策略,并在从配置解析身份验证选项时用作查找键,如以下示例所示:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication()
  .AddJwtBearer()
  .AddJwtBearer("LocalAuthIssuer");
  
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

在最小应用中配置授权策略

身份验证用于针对 API 标识和验证用户的标识。 授权用于验证和证实对 API 中资源的访问,并由通过 AddAuthorization 扩展方法注册的 IAuthorizationService 提供便利。 在以下方案中,添加了 /hello 资源,该资源要求用户提供一个具有 greetings_api 范围声明的 admin 角色声明。

配置资源上的授权要求的过程分为两个步骤,需要:

  1. 全局配置策略中的授权要求。
  2. 将各个策略应用于资源。

在以下代码中,将调用 AddAuthorizationBuilder,这会:

  • 将与授权相关的服务添加到 DI 容器。
  • 返回一个 AuthorizationBuilder,它可用于直接注册身份验证策略。

该代码创建了一个名为 admin_greetings 的新授权策略,该策略封装了两个授权要求:

  • 一个通过 RequireRole 实现的基于角色的要求,面向具有 admin 角色的用户。
  • 一个通过 RequireClaim 实现的基于声明的要求,即用户必须提供 greetings_api 范围声明。

admin_greetings 策略作为 /hello 终结点所需的策略提供。

using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorizationBuilder()
  .AddPolicy("admin_greetings", policy =>
        policy
            .RequireRole("admin")
            .RequireClaim("scope", "greetings_api"));

var app = builder.Build();

app.MapGet("/hello", () => "Hello world!")
  .RequireAuthorization("admin_greetings");

app.Run();

使用 dotnet user-jwts 进行开发测试

本文使用配置了基于 JWT 持有者的身份验证的应用。 基于 JWT 持有者的身份验证要求客户端在请求头中提供令牌来验证其标识和声明。 通常,这些令牌由中央颁发机构(如标识服务器)颁发。

在本地计算机上进行开发时,dotnet user-jwts 工具可用于创建持有者令牌。

dotnet user-jwts create

注意

在项目上调用时,该工具会自动将与生成的令牌匹配的身份验证选项添加到 appsettings.json

可以使用各种自定义项配置令牌。 例如,若要为上述代码中的授权策略所需的 admin 角色和 greetings_api 范围创建令牌,请执行以下操作:

dotnet user-jwts create --scope "greetings_api" --role "admin"

然后,可以在所选的测试工具中将生成的令牌作为标头的一部分发送。 举个使用 curl 的例子:

curl -i -H "Authorization: Bearer {token}" https://localhost:{port}/hello

有关 dotnet user-jwts 工具的详细信息,请阅读完整文档