内容: 本文带大家使用 IdentityServer4 进行对 API 授权保护的基本策略
本文将要讲述如何使用 IdentityServer4 对 API 授权保护以及如何携带 Token 进行访问受保护的 API, 通过 HttpClient 或 Http 请求中的 body 这些我们都可以达到. 那么废话不多说, 开始吧~
首先我们一定要知道, 我们访问要访问一个受安全限制的 API 的锁子是在一个专门的 IdentityServer4 验证服务器. 所以呢, 我们需要创建一个认证服务器. 首先我们创建一个 API 项目.
创建完成之后, 我们再创建一个 Config.cs, 当然这个名字你随意, 但你需要在 DI 注入的时候与其对应. 在 GetSoluction 中定义了我们的 API, 也就是受保护的锁子, 第一个参数是 name, 也就是 API 的名称, 那么后面是显示的名字, 也就是 DisplayName. 在 GetClients 当中我们定义了受信任的客户端, 其中有客户端的 ID, 授权方式, 客户端加密方式, 通过 AllowedScopes 还定义了这个客户端可以访问的 API.
- using IdentityServer4.Models;
- using System.Collections.Generic;
- namespace IdentityServerSolution
- {
- /// <summary>
- /// zaranet 2019.1.26 14.10 create this file
- /// Config 是 IdentityServer 的配置文件, 一会我们需要注册到 DI 层.
- /// </summary>
- public class Config
- {
- /// <summary>
- /// 这个 ApiResource 参数就是我们 API
- /// </summary>
- /// <returns></returns>
- public static IEnumerable<ApiResource> GetSoluction()
- {
- return new[]
- {
- new ApiResource("api1", "MY API")
- };
- }
- public static IEnumerable<Client> GetClients()
- {
- return new List<Client>
- {
- new Client
- {
- ClientId = "Client",
- AllowedGrantTypes = GrantTypes.ClientCredentials,
- ClientSecrets = {
- new Secret("secret".Sha256()),
- },
- AllowedScopes = {"api1"}
- }
- };
- }
- }
- }
我们现在已经写好了关于 IdentityServer4 服务器的配置文件, 那么我们还需要去依赖注入到. NET Core 管道中, 现在我们看一下定义.
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddIdentityServer()
- .AddInMemoryApiResources(Config.GetSoluction())
- .AddInMemoryClients(Config.GetClients())
- .AddDeveloperSigningCredential();
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
- }
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- // 添加认证中间件
- App.UseIdentityServer();
- if (env.IsDevelopment())
- {
- App.UseDeveloperExceptionPage();
- }
- App.UseMvc();
- }
就是这样 - 如果您运行服务器并浏览浏览器 http://localhost: 您的端口 /.well-known/openid-configuration, 您应该会看到所谓的发现文档. 客户端和 API 将使用它来下载必要的配置数据.
首次启动时, IdentityServer 将为您创建一个开发人员签名密钥, 它是一个名为的文件 tempkey.rsa. 您不必将该文件检入源代码管理中, 如果该文件不存在, 将重新创建该文件.
以下是用 PostMan 进行的测试, 以 HttpPost 方式进行请求, 并在 Http Body 中进行编辑请求体上下文, 测试结果如下. 如果三个参数没有问题就返回 token, 如果其中三个参数有一个写错, 那么就会返回 400 错误 (error:invalid_client).
下面在 API 项目中添加控制器:
- [Route("identity")]
- [Authorize]
- [ApiController]
- public class IdentityController : ControllerBase
- {
- [HttpGet]
- public IActionResult Get()
- {
- return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
- }
- }
稍后将使用此控制器来测试授权要求, 以及通过 API 的眼睛可视化声明身份. 现在我们将身份验证服务添加到 DI 和身份验证中间价到管道中, 验证传入令牌以确保它来自受信任的颁发者.
将 Startup 更新为如下所示:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvcCore()
- .AddAuthorization()
- .AddJsonFormatters();
- services.AddAuthentication("Bearer")
- .AddJwtBearer("Bearer", options =>
- {
- options.Authority = "http://localhost:58653";
- options.RequireHttpsMetadata = false;
- options.Audience = "api1";
- });
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
- }
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- App.UseAuthentication();
- if (env.IsDevelopment())
- {
- App.UseDeveloperExceptionPage();
- }
- App.UseMvc();
- }
AddAuthentication 是为了用于将 IdentityServer4 访问令牌验证处理程序将在 DI 中提供身份验证服务. UseAuthentication 将身份验证中间件添加到管道中, 以便在每次调用主机时自动执行身份验证. 如果你现在转到 http://localhost:prot/identity
中是 401 错误的话, 说明 API 已经得到了保护. 配置成功了!, 现在我们要创建我们的客户端了. 去访问受保护的 API 需要携带钥匙, 那么这个钥匙术语叫做令牌, 那就是通往大门的令牌! 现在立刻创建一个控制台程序, 使用令牌访问 API.
首先我们需要安装 IdentityModel, 因为它可以替我们找到元数据.
IdentityModel 包括用于发现端点的客户端库. 这样您只需要知道 IdentityServer 的基地址 - 可以从元数据中读取实际的端点地址:
- var client = new HttpClient();
- var disco = await client.GetDiscoveryDocumentAsync("http://localhost:58653");
- if (disco.IsError)
- {
- Console.WriteLine(disco.Error);
- return;
- }
接下来, 您可以使用发现文档中的信息来请求令牌:
- var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
- {
- Address = disco.TokenEndpoint,
- ClientId = "Client", //id
- ClientSecret = "secret", //pwd
- Scope = "api1" // 请求的 API
- });
- if (tokenResponse.IsError)
- {
- Console.WriteLine(tokenResponse.Error);
- return;
- }
要将访问令牌发送到 API, 通常使用 HTTP Authorization 标头. 这是使用 SetBearerToken 扩展方法完成的:
- var Apiclient = new HttpClient();
- Apiclient.SetBearerToken(tokenResponse.AccessToken);
- var response = await client.GetAsync("http://localhost:58653/identity");
- if (!response.IsSuccessStatusCode)
- {
- Console.WriteLine(response.StatusCode);
- }
- else
- {
- var content = await response.Content.ReadAsStringAsync();
- Console.WriteLine(JArray.Parse(content));
- }
就这样, 我们启动结果如下, 启动顺序, 应先启动身份认证平台, 然后再启动 API, 在启动控制台调试工具.
就这样一个简单的 IdentityServer4 身份认证平台就 OK 了, 现在是不是想要迫切的试一下呢? 哈哈, 关于源代码, 我放到我的 Coding 中了, 地址是: https://coding.net/u/zaranet/p/IdentitySERVER, 当然不要看着简单, 还是自己敲一下吧, 如果你一点都没有碰过 IdentityServer 的话. 下面我们在回顾一下.
我们在 IdentityServerSoluction 中定义了 Config 文件, 用于 Id4 的配置, 主要功能是为了认证模型, 其中还设置了 Client 请求文中的 ClientId 这些参数等等. 那么 IdentItyAPI 就是我们的项目服务, 其中通过 Authorize 标记的都是具有安全保护的 API 控制器, 那么我们就需要去获取我们的 IdentityServerSoluction 中的验证, 这样我们才可以访问, 那么我们就用了. NET Core 控制台程序去模拟了这个过程, 其中涉及了 HttpClient 相关知识. 那么最后返回了我们的相关 token , 这样, 我们可以根据 token 去获取我们想要的 API 服务了!
最后祝大家春运快乐. 下一篇干货在等大家噢!
来源: https://www.cnblogs.com/ZaraNet/p/10323400.html