用Ocelot在ASP.NET Core中实现API网关

295 阅读19分钟

采用微服务架构的冲动一直是软件开发行业的一个可喜趋势。微服务架构是近期最受关注的技术之一--它已被全球许多领先的组织所接受。微服务架构最初是为了解决单体系统的局限性而开发的,在过去几年中,微服务架构的受欢迎程度大幅提高,主要原因是可扩展性、灵活性和性能的提高。

由于基于微服务的应用程序由几个不同的服务组成,你通常需要一个共同的接口或网关来调用这些服务,这样你就可以在一个地方定义和管理所有的关注点,而不是在所有下游服务中复制它们。这正是API网关出现的地方。本文简要讨论了围绕微服务架构的概念,以及你如何与API网关合作,以便有一个一致的方式来连接到微服务。让我们开始吧!

什么是微服务架构?

微服务架构是一种面向服务的架构(SOA)的变体,其中应用程序由轻量级、松散耦合的模块化服务集合组成。这些服务可以建立在各种平台上执行,并独立开发、测试、部署和管理。

微服务架构可以取代长期运行的、复杂的、需要大量资源和管理费用的单体系统。微服务是指具有有限功能集的服务,而不是指用于创建它的代码长度。

什么是API网关?

在构建基于微服务的应用程序时,需要一个API网关,以便有一个实现认证、节流、协调等的中心场所。如果没有API网关,你通常会在每个服务中实现这些功能,因此为每个服务维护这些功能将是一项艰巨的任务。API网关将服务生产者和消费者分离开来,提供一个安全层,因为你不需要直接暴露你的微服务。

一旦它收到一个请求,它就会把它分成多个请求(如果需要),然后把它们路由到适当的下游微服务。你可以利用API网关来集中、管理和监控应用程序的非功能需求,协调跨功能的微服务,并减少往返次数。通过统一管理请求,API网关可以帮助减少延迟并提高安全性。

下图展示了一个用于连接两个下游微服务的API网关,这两个微服务分别是客户和产品。

API Gateway architecture diagram

通常情况下,微服务的消费者或客户端不会直接与之通信。相反,如上图所示,API网关提供了一个单一的入口点,用于引导流量到各种微服务。因此,客户没有任何直接访问服务的权利,也不能利用服务。如果你的API网关在防火墙后面,你可以在攻击面周围增加一个额外的保护层。

API网关模式与两个著名的四人帮设计模式相对应。Facade和Adapter。像Facade设计模式一样,API网关为消费者提供了一个API,同时封装了内部架构。API网关能够像Adapter设计模式那样实现通信和协作,即使接口不兼容。

为什么我们需要一个API网关?

一个基于微服务的应用程序包括许多使用同质或异质技术构建的不同微服务。API网关为外部消费者提供了一个集中的入口点,而不管下游微服务的数量或构成如何。API网关通常可以包含一个额外的速率限制和安全层。

以下是API网关的主要好处。

  • 更好的隔离。API网关通过防止对内部关注点的直接访问来提供隔离。因此,它可以将服务发现、版本和其他内部细节从服务消费者或客户那里封装起来。此外,API网关使你能够增加更多的微服务或改变边界而不影响外部消费者。
  • 提高安全性。API网关为你的微服务提供了一个安全层,可以帮助防止SQL注入、拒绝服务(DoS)等攻击载体。你可以利用API网关来验证用户。如果一个特定的服务消费者需要来自多个服务的数据,你只需要对用户进行一次认证,从而减少延迟并使你的认证机制在整个应用中保持一致。
  • 性能指标。由于API网关是一个单一的组件,所有的请求和响应都流经它,它是一个收集指标的好地方。例如,你可以测量转发到下游微服务的请求的数量和执行时间。
  • 降低复杂性。微服务有特定的共同关注点,包括日志、速率限制、安全等。你需要更多的时间在你的应用程序使用的每个微服务中开发这些问题。API网关可以消除这种代码重复,从而减少创建这些组件所需的努力。

API网关和反向代理

围绕反向代理和API网关有很多混淆。虽然它们之间有相似之处,但两者之间也有微妙的区别。

反向代理服务器通常位于防火墙后面,将请求从客户端路由到适当的后端服务器。反向代理是一个轻量级的API网关,包括一些基本的安全和监控功能。因此,如果你需要一个具有基本功能的API网关,一个反向代理服务器应该足够了。请注意,反向代理不能进行转换或协调。

API网关位于客户端和一组后端服务之间,提供比反向代理服务器更广泛的安全和监控能力。API网关为全面的服务协调、转换和调解提供支持。它还提供了对传输安全的广泛支持--比简单的代理所能提供的要多得多。

介绍一下Ocelot

在这篇文章中,我们将使用Ocelot API网关。它是一个轻量级、开源、可扩展和快速的API网关,基于.NET Core,专门为微服务架构设计。基本上,它是一套旨在与ASP.NET Core一起工作的中间件。它有几个特点,如路由、缓存、安全、速率限制等。

基于订单处理的微服务应用

现在让我们通过实现一个具体的例子来实践我们到目前为止所学到的概念。我们将建立一个订单处理应用程序,说明如何使用API网关来调用每个服务,分别使用Customer和Product微服务来检索客户和产品数据。

通常情况下,一个基于订单处理微服务的应用程序包括诸如产品、客户、订单、OrderDetails等微服务。在这个例子中,我们将考虑一个最小化的基于微服务的应用。这个应用将包含一个API网关和两个微服务--产品和客户微服务。这个应用将是简单的,这样我们就可以更专注于构建API网关。

先决条件

为了执行本文所示的代码示例,以下是你在系统中应该安装的最低要求。

  • .NET 5 SDK
  • Visual Studio 2019

解决方案的结构

你要构建的应用程序将由以下项目组成,作为单个Visual Studio解决方案的一部分。

  • OrderProcessing 项目 - 该项目代表API网关,负责从客户端获取请求并调用微服务。
  • OrderProcessing.Customerproject - 该项目定义了用于表示客户微服务的类和接口。
  • OrderProcessing.Productproject - 这个项目定义了用于表示产品微服务的类型。

客户微服务项目将由以下类和接口组成。

  • Customer class - 这代表客户实体类。
  • ICustomerRepository 接口 - 这代表了客户资源库的接口。
  • CustomerRepositoryclass - 这代表了实现ICustomerRepository 接口的客户资源库类。
  • CustomerController class - 该类代表客户微服务的API控制器。

产品微服务项目将包含以下类型。

  • Product class - 该类代表产品实体。
  • IProductRepository 接口--这代表产品库的接口。
  • ProductRepository class - 这是产品库的类,实现了 接口。IProductRepository
  • ProductController class - 这代表产品微服务的API控制器类。

下图显示了完成后的应用程序的解决方案结构的样子。

Solution Structure of the OrderProcessing Application

创建订单处理应用程序的项目

打开一个命令外壳,输入以下命令来创建我们需要的三个ASP.NET项目。

dotnet new web --framework "net5.0" -o OrderProcessing
dotnet new webapi --framework "net5.0" -o OrderProcessing.Customer
dotnet new webapi --framework "net5.0" -o OrderProcessing.Product

OrderProcessing 项目是一个空的ASP.NET项目,而另外两个项目是WebAPI项目。确保你从这两个项目中删除默认的控制器和实体类,因为我们不需要它们。

创建客户微服务

创建一个新的文件,名为 Customer.cs的新文件,在 OrderProcessing.Customer项目的根部,并在其中加入以下代码。

// OrderProcessing.Customer/Customer.cs

using System;

namespace OrderProcessing.Customer
{
    public class Customer
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string EmailAddress { get; set; }
    }
}

创建CustomerRepository类

ICustomerRepository 在一个名为 ICustomerRepository.cs的文件中创建一个名为""的接口。 OrderProcessing.Customer的文件中创建一个名为 的接口,并在其中加入以下代码。

// OrderProcessing.Customer/ICustomerRepository.cs

using System.Collections.Generic;
using System.Threading.Tasks;

namespace OrderProcessing.Customer
{
    public interface ICustomerRepository
    {
        public Task<List<Customer>> GetAllCustomers();
    }
}

在项目的根部创建实现ICustomerRepository 接口的CustomerRepository 类,如以下代码片段所示: OrderProcessing.Customer如下面的代码片段所示。

// OrderProcessing.Customer/CustomerRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace OrderProcessing.Customer
{
    public class CustomerRepository : ICustomerRepository
    {
        private readonly List<Customer> customers = new List<Customer>();
        public CustomerRepository()
        {
            customers.Add(new Customer()
            {
                Id = Guid.NewGuid(),
                FirstName = "Joydip",
                LastName = "Kanjilal",
                EmailAddress = "joydipkanjilal@yahoo.com"
            });

            customers.Add(new Customer()
            {
                Id = Guid.NewGuid(),
                FirstName = "Steve",
                LastName = "Smith",
                EmailAddress = "stevesmith@yahoo.com"
            });
        }
        public Task<List<Customer>> GetAllCustomers()
        {
            return Task.FromResult(customers);
        }
    }
}

创建CustomerController类

在项目的Controllers 文件夹中,创建一个API控制器,命名为 OrderProcessing.Customer项目的文件夹中,创建一个名为CustomerController 的API控制器,并将默认代码替换为以下内容。

// OrderProcessing.Customer/Controllers/CustomerController.cs

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace OrderProcessing.Customer.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CustomerController : ControllerBase
    {
        private readonly ICustomerRepository _customerRepository;
        public CustomerController(ICustomerRepository customerRepository)
        {
            _customerRepository = customerRepository;
        }

        [HttpGet]
        public async Task<ActionResult<List<Customer>>> GetAllCustomers()
        {
            return await _customerRepository.GetAllCustomers();
        }
    }
}

创建 "产品 "微服务

在项目的根部创建一个新的文件,名为 Product.cs的新文件,并在该项目根目录下添加以下代码 OrderProcessing.Product项目的根部创建一个新文件,并在其中加入以下代码。

// OrderProcessing.Product/Product.cs

using System;

namespace OrderProcessing.Product
{
    public class Product
    {
        public Guid Id { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public int Quantity_In_Stock { get; set; }
        public decimal Unit_Price { get; set; }
    }
}

创建ProductRepository类

接下来,你应该在项目的根目录下创建一个新的文件,名为 IProductRepository.cs的新文件,并编写以下代码来创建 OrderProcessing.Product项目中创建一个新文件,并编写以下代码来创建IProductRepository 接口。

// OrderProcessing.Product/IProductRepository.cs

using System.Collections.Generic;
using System.Threading.Tasks;

namespace OrderProcessing.Product
{
    public interface IProductRepository
    {
        public Task<List<Product>> GetAllProducts();
    }
}

在项目的根部创建实现IProductRepository 接口的ProductRepository 类,如下图所示 OrderProcessing.Product如下面的代码片段所示。

// OrderProcessing.Product/ProductRepository.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace OrderProcessing.Product
{
    public class ProductRepository : IProductRepository
    {
        private readonly List<Product> products = new List<Product>();
        public ProductRepository()
        {
            products.Add(new Product
            {
                Id = Guid.NewGuid(),
                Code = "P0001",
                Name = "Lenovo Laptop",
                Quantity_In_Stock = 15,
                Unit_Price = 125000
            });

            products.Add(new Product
            {
                Id = Guid.NewGuid(),
                Code = "P0002",
                Name = "DELL Laptop",
                Quantity_In_Stock = 25,
                Unit_Price = 135000
            });

            products.Add(new Product
            {
                Id = Guid.NewGuid(),
                Code = "P0003",
                Name = "HP Laptop",
                Quantity_In_Stock = 20,
                Unit_Price = 115000
            });
        }
        public Task<List<Product>> GetAllProducts()
        {
            return Task.FromResult(products);
        }
    }
}

创建ProductController类

在项目的Controllers 文件夹中,创建一个名为 OrderProcessing.Product项目的文件夹中,创建一个名为ProductController 的API控制器,并将默认代码替换为以下内容。

// OrderProcessing.Product/ProductController.cs

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace OrderProcessing.Product.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        private readonly IProductRepository _productRepository;
        public ProductController(IProductRepository customerRepository)
        {
            _productRepository = customerRepository;
        }

        [HttpGet]
        public async Task<ActionResult<List<Product>>> GetAllCustomers()
        {
            return await _productRepository.GetAllProducts();
        }
    }
}

使用Ocelot实现API网关

现在,项目中已经创建了必要的文件,让我们使用Ocelot实现API网关。

在继续前进之前,你应该知道上游下游这两个术语。上游指的是客户端向API网关发送的请求,而下游则与API网关向特定微服务发送的请求有关。

安装所需的软件包

要使用Ocelot,你必须在你的ASP.NET Core项目中安装它。在我们的案例中,你将在OrderProcessing 项目中安装Ocelot。你可以通过在Visual Studio IDE中使用NuGet包管理器来完成。或者,你可以在包管理器控制台窗口执行以下命令。

Install-Package Ocelot

实施路由

Ocelot API网关接受一个传入的HTTP请求,并将其转发到下游服务。Ocelot利用路由来定义一个请求如何从一个地方被路由到另一个地方。在这个项目中添加一个新文件,名为 ocelot.json的新文件,并在其中加入以下内容。

// OrderProcessing/Ocelot.json
{
   "Routes":[
      //Customer API{
         "DownstreamPathTemplate":"/api/Customer",
         "DownstreamScheme":"http",
         "DownstreamHostAndPorts":[
            {
               "Host":"localhost",
               "Port":"20057"
            }
         ],
         "UpstreamPathTemplate":"/Customer",
         "UpstreamHttpMethod":[
            "GET"
         ]
      },
      //Product API{
         "DownstreamPathTemplate":"/api/Product",
         "DownstreamScheme":"http",
         "DownstreamHostAndPorts":[
            {
               "Host":"localhost",
               "Port":"32345"
            }
         ],
         "UpstreamPathTemplate":"/Product",
         "UpstreamHttpMethod":[
            "GET"
         ]
      }
   ]
}

上述配置指定了客户和产品微服务的下游和上游元数据(方案、路径、端口)。因此,在使用上游元数据调用这里指定的端点时,请求会被路由到下游元数据中指定的适当的下游服务。换句话说,下游元数据用于指定内部服务的URL,以便在API网关收到新的请求时将请求重定向到。

AddOcelot 你应该通过调用Startup 类中的ConfigureServices 方法将Ocelot添加到服务容器中,如下图所示。

// OrderProcessing/Startup.cs

// ... existing code

public void ConfigureServices(IServiceCollection services) 
{
  services.AddOcelot(Configuration);
}

// ... existing code

接下来,你应该在Startup 类的Configure 方法中通过调用UseOcelot 扩展方法来启用Ocelot,如下图所示。

// OrderProcessing/Startup.cs

// ... existing code

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
  }

  app.UseRouting();
  app.UseOcelot();

  app.UseEndpoints(endpoints => {
    endpoints.MapGet("/", async context => {
      await context.Response.WriteAsync("Hello World!");
    });
  });
}

// ... existing code

运行项目

现在,请确保你已经将这三个项目作为启动项目。要做到这一点,请遵循以下步骤。

  1. 在解决方案资源管理器窗口中,右键单击解决方案文件。
  2. 点击 "属性"。
  3. 在 "属性页 "窗口中,选择 "多个启动项目 "单选按钮。

Multiple startup projects option in Visual Studio

  1. 点击 "OK"。

按F5键,运行该应用程序。现在从Postman或你选择的任何其他HTTP客户端向以下URL发送HTTP获取请求。

http://localhost:39469/Customer

客户控制器的HTTP Get方法将被执行,输出结果将是这样的。

The Customer Microservice in Execution!

从Postman发送一个HTTP Get请求到下面的URL。

http://localhost:39469/Product

请求首先进入API网关。接下来,API网关将请求路由到正确的下游微服务,具体内容在 ocelot.json.ProductController 中名为GetAllProducts 的HTTP获取方法将被调用,输出结果将是这样的。

The Product Microservice in Execution!

实施速率限制

速率限制是一种控制网络流量的技术。它设置了一个限制,即在一个特定的时期内,你可以执行多少次特定的活动--例如,访问一个特定的资源,登录到一个账户,等等。通常情况下,速率限制会跟踪IP地址和请求之间的时间。IP地址有助于确定一个特定请求的来源。

速率限制解决方案善于跟踪每个请求之间所经过的时间以及特定时期内的请求总数。如果一个IP地址在一个特定的时间范围内发出过多的请求,限速解决方案将在一个特定时期内拒绝这些请求。

为了防止你的下游服务负担过重,Ocelot启用了对上游请求的速率限制。下面的配置说明了你如何在Ocelot中指定速率限制。

// OrderProcessing/Ocelot.json

"RateLimitOptions":{
   "ClientWhitelist":[      
   ],
   "EnableRateLimiting":true,
   "Period":"5s",
   "PeriodTimespan":1,
   "Limit":1,
   "HttpStatusCode":429
}

现在让我们来简要地检查一下这些选项中的每一个。

  • ClientWhitelist setting - 这是一个数组,用于指定不应受到速率限制影响的客户。
  • EnableRateLimiting setting - 这是一个布尔值。 true如果你想启用速率限制。 false否则。
  • HttpStatusCode setting - 这是用于指定当速率限制发生时返回的HTTP状态代码
  • Period setting - 这是指定速率限制适用的持续时间,这反过来意味着如果你在这个持续时间内发出的请求超过了允许的范围,你就需要等待 中指定的持续时间。PeriodTimespan
  • PeriodTimespan setting - 这是用来指定你可以重新尝试连接到服务的时间。
  • Limit setting - 这指定了在 中指定的持续时间内允许的最大请求数。Period

让我们假设速率限制只应用于产品微服务。更新后的 ocelot.json文件现在看起来是这样的。

// OrderProcessing/Ocelot.json

{
   "Routes":[
      //Customer API
     {
         "DownstreamPathTemplate":"/api/Customer",
         "DownstreamScheme":"http",
         "DownstreamHostAndPorts":[
            {
               "Host":"localhost",
               "Port":"20057"
            }
         ],
         "UpstreamPathTemplate":"/Customer",
         "UpstreamHttpMethod":[
            "GET"
         ]
      },
      //Product API
      {
         "DownstreamPathTemplate":"/api/Product",
         "DownstreamScheme":"http",
         "DownstreamHostAndPorts":[
            {
               "Host":"localhost",
               "Port":"32345"
            }
         ],
         "RateLimitOptions":{
            "ClientWhitelist":[
               
            ],
            "EnableRateLimiting":true,
            "Period":"5s",
            "PeriodTimespan":1,
            "Limit":1
         },
         "UpstreamPathTemplate":"/Product",
         "UpstreamHttpMethod":[
            "GET"
         ]
      }
   ]
}

现在,运行应用程序并发送频繁的请求(每5秒超过一个),你会看到以下错误。

Rate Limiting at work!

实施缓存

缓存是网络应用中广泛使用的一种技术,用于将数据保存在内存中,以便在应用需要时可以快速访问相同的数据。Ocelot提供对基本缓存的支持。为了利用它,你应该安装 Ocelot.Cache.CacheManagerNuGet包,如下图所示。

Install-Package Ocelot.Cache.CacheManager

接下来,你应该在ConfigureServices 方法中使用以下代码配置缓存。

// OrderProcessing/Startup.cs

// ... existing code ...

public void ConfigureServices(IServiceCollection services)
{
  services.AddOcelot(Configuration)
    .AddCacheManager(x =>
      {
        x.WithDictionaryHandle();
      });
}

// ... existing code ...

最后,你应该在路由配置中使用以下设置来指定特定路由的缓存。

// OrderProcessing/Ocelot.json

// ... existing settings ...

"Routes":[
   //Customer API{
      "DownstreamPathTemplate":"/api/Customer",
      "DownstreamScheme":"http",
      "DownstreamHostAndPorts":[
         {
            "Host":"localhost",
            "Port":"20057"
         }
      ],
      "FileCacheOptions":{
         "TtlSeconds":30,
         "Region":"customercaching"
      },
      "UpstreamPathTemplate":"/Customer",
      "UpstreamHttpMethod":[
         "GET"
      ]
   }
]

// ... existing settings ...

在这里,我们将TtlSeconds 设置为30秒,这意味着缓存将在这个时间过后失效。注意,你应该在FileCacheOptions 部分指定你的缓存配置。Region 的设置确定了缓存中包含数据的区域。这样你就可以通过使用Ocelot的管理API来清除该区域。

为了测试这一点,你可以在CustomerController 类中名为GetAllCustomers 的HTTP获取方法上设置一个断点。当你执行应用程序并向该端点发送HTTP Get请求时,该断点将像往常一样被击中。然而,在30秒内(这是我们指定的持续时间)对同一个端点的所有后续调用将获取数据,但断点将不再被击中。

实现相关的ID

Ocelot使客户端能够在头中向服务器发送一个请求ID。一旦这个请求ID在中间件管道中可用,你就可以把它和其他信息一起记录下来。如果需要,Ocelot还可以将这个请求ID转发给下游服务。相关ID是附加到每个请求和响应的唯一标识符,用于跟踪分布式应用中的请求和响应。在与Ocelot合作追踪请求时,你可以使用请求ID或相关ID。

请求标识(request Id)和相关标识(correlation ID)的主要区别在于,前者唯一地识别每一个HTTP请求,而后者则是附加在特定请求-响应链上的唯一标识。虽然你可以对每个HTTP请求使用 Request-Id用于每个HTTP请求,你可以将 X-Correlation-Id用于一个请求和响应的事件链。 X-Correlation-Id是附加到下游请求的HTTP头的名称,用于跟踪流经多个后端服务的HTTP请求。

Ocelot必须知道它所运行的URL,以便执行某些管理配置。这就是BaseUrl ,在 ocelot.json文件中指定的。请注意,这个URL应该是你的客户将看到API网关运行的URL。

以下是该文件的完整源代码 ocelot.json文件的完整源代码供你参考。

// OrderProcessing/Ocelot.json

{
   "Routes":[
      //Customer API
     {
         "DownstreamPathTemplate":"/api/Customer",
         "DownstreamScheme":"http",
         "DownstreamHostAndPorts":[
            {
               "Host":"localhost",
               "Port":"20057"
            }
         ],
         "FileCacheOptions":{
            "TtlSeconds":30,
            "Region":"customercaching"
         },
         "UpstreamPathTemplate":"/Customer",
         "UpstreamHttpMethod":[
            "GET"
         ]
      },
      //Product API
     {
         "DownstreamPathTemplate":"/api/Product",
         "DownstreamScheme":"http",
         "DownstreamHostAndPorts":[
            {
               "Host":"localhost",
               "Port":"32345"
            }
         ],
         "RateLimitOptions":{
            "ClientWhitelist":[
               
            ],
            "EnableRateLimiting":true,
            "Period":"5s",
            "PeriodTimespan":1,
            "Limit":1
         },
         "UpstreamPathTemplate":"/Product",
         "UpstreamHttpMethod":[
            "GET"
         ]
      }
   ],
   "GlobalConfiguration":{
      "RequestIdKey":"X-Correlation-Id",
      "BaseUrl":"http://localhost:39469"
   }
}

总结

为你的业务需求选择一个示范性的架构,是构建灵活、可扩展和高性能的应用程序的第一步,也是最重要的一步。微服务架构最显著的优势之一是它对异质平台和技术的支持。

你的API网关可以管理诸如安全、速率限制、性能和可扩展性等问题。然而,你应该注意处理它带来的复杂性和单点故障的风险。此外,当你使用API网关构建基于微服务的应用程序时,会有一个学习曲线。可能的性能下降是你必须处理的另一个问题。

本文中构建的OrderProcessing应用程序的完整源代码可以在这里找到。

除此以外。用Auth0保证ASP.NET Core的安全

用Auth0保证ASP.NET Core应用程序的安全是很容易的,并带来了很多伟大的功能。有了Auth0,你只需要写几行代码就可以得到一个坚实的身份管理解决方案单点登录、对社会身份提供者(如Facebook、GitHub、Twitter等)的支持,以及对企业身份提供者(如活动目录、LDAP、SAML、自定义等)的支持。

在ASP.NET Core上,你需要在你的Auth0管理仪表板上创建一个API,并在你的代码上改变一些东西。要创建一个API,你需要注册一个免费的Auth0账户。之后,你需要进入仪表板的API部分,点击 "创建API"。在显示的对话框中,你可以将你的API的名称设置为 "书籍",标识符"http://books.mycompany.com",并将签名算法设为 "RS256"。

Creating API on Auth0

在这之后,你必须把对 services.AddAuthentication()方法中的 ConfigureServices()的方法,如下:Startup

string authority = $"https://{Configuration["Auth0:Domain"]}/";
string audience = Configuration["Auth0:Audience"];

services.AddAuthentication(options =>
{
  options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
  options.Authority = authority;
  options.Audience = audience;
});

Configure()``Startup 方法的主体中,你还需要添加一个调用到 app.UseAuthentication()app.UseAuthorization()如下图所示。

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

请确保你按照上面的顺序调用这些方法。这是至关重要的,这样一切才能正常工作。

最后,将以下元素添加到 appsettings.json配置文件。

{
  "Logging": {
    // ...
  },
  "Auth0": {
    "Domain": "YOUR_DOMAIN",
    "Audience": "YOUR_AUDIENCE"
  }
}

:替换占位符 YOUR_DOMAINYOUR_AUDIENCE替换为你在创建Auth0账户时指定的域的实际值以及你分配给API的标识符


© 2013-2021 Auth0公司。保留所有权利。