使用Asp.net核心创建另一个Web api的代理

我正在开发一个ASP.Net Core Web应用程序,我需要为另一个(外部)Web服务创建一种“身份validation代理”。

我的身份validation代理的意思是我将通过我的Web应用程序的特定路径接收请求,并且必须检查这些请求的标头以获取我之前发布的身份validation令牌,然后将所有请求重定向到相同的请求字符串/内容到我的应用程序将通过HTTP Basic身份validation进行身份validation的外部Web API。

这是伪代码的整个过程

  • 客户端通过对我之前发送给他的唯一URL进行POST来请求令牌
  • 我的应用程序向他发送了一个唯一的令牌以响应此POST
  • 客户端向我的应用程序的特定URL发出GET请求,例如/extapi并在HTTP标头中添加auth-token
  • 我的应用程序获取请求,检查auth-token是否存在且有效
  • 我的应用程序对外部Web API执行相同的请求,并使用BASIC身份validation对请求进行身份validation
  • 我的应用程序从请求中接收结果并将其发送回客户端

这就是我现在所拥有的。 它似乎工作正常,但我想知道它是否真的应该这样做,或者是否有更优雅或更好的解决方案? 从长远来看,该解决方案是否会产生问题以扩展应用程序?

 [HttpGet] public async Task GetStatement() { //TODO check for token presence and reject if issue var queryString = Request.QueryString; var response = await _httpClient.GetAsync(queryString.Value); var content = await response.Content.ReadAsStringAsync(); Response.StatusCode = (int)response.StatusCode; Response.ContentType = response.Content.Headers.ContentType.ToString(); Response.ContentLength = response.Content.Headers.ContentLength; await Response.WriteAsync(content); } [HttpPost] public async Task PostStatement() { using (var streamContent = new StreamContent(Request.Body)) { //TODO check for token presence and reject if issue var response = await _httpClient.PostAsync(string.Empty, streamContent); var content = await response.Content.ReadAsStringAsync(); Response.StatusCode = (int)response.StatusCode; Response.ContentType = response.Content.Headers.ContentType?.ToString(); Response.ContentLength = response.Content.Headers.ContentLength; await Response.WriteAsync(content); } } 

_httpClient是一个HttpClient类,在其他地方实例化并且是一个单例并且BaseAddresshttp://someexternalapp.com/api/

此外,令牌创建/令牌检查比手动更简单吗?

我最终实现了一个受Asp.Net的GitHub项目启发的代理中间件。

它基本上实现了一个中间件,它读取收到的请求,从中创建一个副本并将其发送回配置的服务,从服务中读取响应并将其发送回调用者。

以下是ASP.NET Core的代理库的基本实现:

这不会实现授权,但对于使用ASP.NET Core寻找简单反向代理的人可能会有用。 我们只将它用于开发阶段。

 using System; using System.Globalization; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; namespace Sample.Proxy { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddLogging(options => { options.AddDebug(); options.AddConsole(console => { console.IncludeScopes = true; }); }); services.AddProxy(options => { options.MessageHandler = new HttpClientHandler { AllowAutoRedirect = false, UseCookies = true }; options.PrepareRequest = (originalRequest, message) => { var host = GetHeaderValue(originalRequest, "X-Forwarded-Host") ?? originalRequest.Host.Host; var port = GetHeaderValue(originalRequest, "X-Forwarded-Port") ?? originalRequest.Host.Port.Value.ToString(CultureInfo.InvariantCulture); var prefix = GetHeaderValue(originalRequest, "X-Forwarded-Prefix") ?? originalRequest.PathBase; message.Headers.Add("X-Forwarded-Host", host); if (!string.IsNullOrWhiteSpace(port)) message.Headers.Add("X-Forwarded-Port", port); if (!string.IsNullOrWhiteSpace(prefix)) message.Headers.Add("X-Forwarded-Prefix", prefix); return Task.FromResult(0); }; }); } private static string GetHeaderValue(HttpRequest request, string headerName) { return request.Headers.TryGetValue(headerName, out StringValues list) ? list.FirstOrDefault() : null; } public void Configure(IApplicationBuilder app) { app.UseWebSockets() .Map("/api", api => api.RunProxy(new Uri("http://localhost:8833"))) .Map("/image", api => api.RunProxy(new Uri("http://localhost:8844"))) .Map("/admin", api => api.RunProxy(new Uri("http://localhost:8822"))) .RunProxy(new Uri("http://localhost:8811")); } public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseIISIntegration() .UseStartup() .Build(); host.Run(); } } }