ASP.NET Core Web API 集成 IdentityServer4 与 Swagger OAuth2 授权流程
在现代微服务架构中,API 安全性至关重要。本文将演示如何在 ASP.NET Core Web API 中集成 IdentityServer4 实现基于 OpenID Connect 的令牌认证,并通过 Swagger UI 提供交互式授权体验。整个方案采用内存存储配置,适用于开发与测试阶段。
一、搭建 IdentityServer4 认证中心
新建一个空的 ASP.NET Core Web 项目(目标框架 .NET Core 3.1 或更高版本),然后通过 NuGet 安装 IdentityServer4 和 IdentityServer4.Quickstart.UI:
dotnet add package IdentityServer4
dotnet add package IdentityServer4.Quickstart.UI
接着,在项目根目录执行以下命令以自动引入基础 UI 页面(登录页、授权页等):
dotnet is4ui
若该命令不可用,可手动克隆官方 Quickstart UI 并复制 Quickstart 文件夹至项目中,确保其包含 Controllers、Views 等子目录。
二、定义认证资源与客户端
创建 Configuration/IdentityConfig.cs 文件,封装资源配置逻辑:
using IdentityServer4.Models;
using System.Collections.Generic;
namespace AuthCenter.Configuration
{
public static class IdentityConfig
{
public static IEnumerable<IdentityResource> IdentityScopes => new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
public static IEnumerable<ApiResource> ApiResources => new[]
{
new ApiResource("protected_api", "Protected Backend Service")
{
Scopes = { "api.read", "api.write" }
}
};
public static IEnumerable<Client> Clients => new[]
{
new Client
{
ClientId = "swagger_client",
ClientName = "Swagger Interactive Docs",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:5002/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { "http://localhost:5002/" },
AllowedScopes = { "openid", "profile", "protected_api" },
RequireConsent = false
}
};
}
}
注意:此处将 API 资源拆分为更细粒度的作用域(api.read / api.write),便于后续权限控制扩展。
三、注册并启用 IdentityServer4
在 Startup.ConfigureServices 中注册服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(IdentityConfig.IdentityScopes)
.AddInMemoryApiResources(IdentityConfig.ApiResources)
.AddInMemoryClients(IdentityConfig.Clients)
.AddTestUsers(TestUsers.Users); // 内置测试用户:alice/bob
}
在 Configure 方法中启用中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer(); // 必须在 UseAuthentication 之前
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
}
修改 launchSettings.json 将应用端口设为 5000,启动后访问 http://localhost:5000/.well-known/openid-configuration 可验证配置是否生效。
四、构建受保护的 API 服务
新建另一个 ASP.NET Core Web API 项目,安装以下 NuGet 包:
IdentityServer4.AccessTokenValidationSwashbuckle.AspNetCore
在 Startup.ConfigureServices 中添加 JWT Bearer 认证支持:
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000";
options.Audience = "protected_api";
options.RequireHttpsMetadata = false;
});
services.AddAuthorization(options =>
{
options.AddPolicy("ReadScope", policy =>
policy.RequireClaim("scope", "api.read"));
options.AddPolicy("WriteScope", policy =>
policy.RequireClaim("scope", "api.write"));
});
五、集成 Swagger 并启用 OAuth2 登录
配置 Swagger 以支持隐式授权流:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Secure API", Version = "v1" });
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("http://localhost:5000/connect/authorize"),
Scopes = new Dictionary<string, string>
{
{ "api.read", "Read protected data" },
{ "api.write", "Modify protected data" }
}
}
}
});
c.OperationFilter<SecurityRequirementsOperationFilter>();
});
// 自定义过滤器:为标记 [Authorize] 的操作注入安全要求
public class SecurityRequirementsOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var authAttributes = context.MethodInfo.GetCustomAttributes(true)
.Union(context.MethodInfo.DeclaringType.GetCustomAttributes(true))
.OfType<AuthorizeAttribute>();
if (authAttributes.Any())
{
operation.Security = new List<OpenApiSecurityRequirement>
{
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "oauth2"
}
},
new[] { "api.read" } // 默认作用域
}
}
};
}
}
}
在 Configure 方法中启用中间件:
app.UseAuthentication();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Secure API v1");
c.OAuthClientId("swagger_client");
c.OAuthAppName("Secure API - Interactive Docs");
c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
});
将 API 项目端口设为 5002(需与 IdentityServer 中 RedirectUris 一致),启动后访问 http://localhost:5002/swagger 即可见 "Authorize" 按钮。
六、控制器示例与权限控制
在 API 控制器中使用策略或作用域进行细粒度控制:
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
[HttpGet("public")]
public IActionResult GetPublic() => Ok("This endpoint requires no auth.");
[HttpGet("restricted")]
[Authorize(Policy = "ReadScope")]
public IActionResult GetRestricted() => Ok("You have 'api.read' scope.");
[HttpPost("update")]
[Authorize(Policy = "WriteScope")]
public IActionResult UpdateData() => Ok("Write access granted.");
}
当调用带 [Authorize] 特性的接口时,Swagger 会显示锁形图标;点击 Authorize 后跳转至 IdentityServer 登录页,成功后自动携带 Access Token 发起请求,响应头中将包含 Authorization: Bearer <token>。