前言
此篇介绍的并不是一个解决方案,而是一个简单示例。需求
比如 A 公司想用 B 公司的 WebAPI 接口,B 公司就需提供一套开放 WebAPI 接口的机制。
思路
- 注册,先决条件:
- A 公司(Client)需先到 B 公司处(IdentityServer)注册一个标识符(ClientId),用于甄别对象
- 注册时,需配置密钥(ClientSecret),用于认证
- 注册时,需配置要使用的 WebAPI 列表 ,用于授权
- 请求 Token:
- A 使用注册好的 ClientId、ClientSecret、Scope(WebAPI 列表)发起请求
- B 解析 A 的请求参数,如果验证通过就向 A 颁发 Token
- 请求 WebAPI:
- A 将 Token 附加在请求头中请求 B 的 WebAPI
- B 解析 A 的 Token ,如果验证通过则允许访问 WebAPI
实现
-
注册( A 公司需先在B公司的认证服务中配置好信息 ):
-
使用模板创建 B 的 IdentityServer 服务
dotnet new is4empty -n B.IdentityServer
-
配置 B 的 WebAPI 资源(Config.cs)
public static IEnumerable<ApiResource> Apis => new[]{ new ApiResource("B.OpenAPI","开放接口") { Scopes = { "B.OpenAPI" } } };
-
配置 B 的 WebAPI 范围(Config.cs)
public static IEnumerable<ApiScope> ApiScopes => new[] { new ApiScope("B.OpenAPI")};
-
配置 A 客户端(Config.cs)
public static IEnumerable<Client> Clients => new[] { new Client { ClientId = "A", AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets = { new Secret("A.Secret".Sha256()) }, AllowedScopes = { "B.OpenAPI" } } };
-
-
创建 B 公司需要开放的 WebAPI
-
创建一个 WebAPI 项目
dotnet new webapi -n B.WebAPI
-
启用认证和授权中间件(Startup.cs -> Configure())
app.UseAuthentication(); // 认证 app.UseAuthorization(); // 授权
-
安装 JwtBearer 包(NuGet 管理器)
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
-
配置认证服务(Startup.cs -> ConfigureServices())
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { options.Authority = "http://localhost:5001"; options.RequireHttpsMetadata = false; });
-
在 WebAPI 中启用授权,以保护 WebAPI
[Authorize] public class WeatherForecastController : ControllerBase {}
-
-
创建 A 公司的客户端,请求 B 公司的 WebAPI
-
创建一个 控制台 项目
dotnet new console -n A.Client
-
安装 IdentityModel 包(NuGet 管理器)
Install-Package IdentityModel
-
A 模拟请求 B 需要授权的 WebAPI
var client = new HttpClient(); // 服务发现 B 公司的开放文档 var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5001"); // 获取 Token var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { Address = disco.TokenEndpoint, ClientId = "A", ClientSecret = "A.Secret", Scope = "B.OpenAPI" }); // 请求 B 公司 WebAPI var apiClient = new HttpClient(); apiClient.SetBearerToken(tokenResponse.AccessToken); // 设置 Bearer var response = await apiClient.GetAsync("http://localhost:5002/WeatherForecast"); var content = await response.Content.ReadAsStringAsync(); Console.WriteLine(JArray.Parse(content));
-
源码
参考
官方文档 - Protecting an API using Client Credentials