首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用ASP.NET内核创建另一个Web API的代理

使用ASP.NET内核创建另一个Web API的代理
EN

Stack Overflow用户
提问于 2018-06-25 07:03:14
回答 2查看 0关注 0票数 0

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

我所说的身份验证代理的意思是,我将通过我的Web应用程序的特定路径接收请求,并必须检查这些请求的头,以获得我将在前面发出的身份验证令牌,然后将具有相同请求字符串/内容的所有请求重定向到外部Web API,我的应用程序将通过HTTP Basic auth对其进行身份验证。

以下是伪代码的整个过程

  • 客户端通过向我之前发送给他的唯一URL发送一个帖子来请求一个令牌
  • 我的应用程序给他发了一个独特的标记来回应这个帖子。
  • 客户端向我的应用程序的特定URL发出GET请求,比如说/extapi,并在HTTP报头中添加auth令牌。
  • 我的应用程序收到请求,检查令牌是否存在并且有效。
  • 我的应用程序对外部web api执行相同的请求,并使用基本身份验证对请求进行身份验证。
  • 我的应用程序接收来自请求的结果并将其发送回客户端。

这是我现在所拥有的。它看起来很好,但我想知道这是否真的是应该这样做,还是没有一个更优雅或更好的解决方案?从长远来看,该解决方案是否会为应用程序的扩展带来问题?

代码语言:txt
复制
[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/

另外,是否有一种比手动进行令牌创建/令牌检查更简单的方法?

EN

回答 2

Stack Overflow用户

发布于 2018-06-25 15:37:39

这并不实现授权,但对于使用ASP.NETCore寻找简单的反向代理的人来说可能很有用。我们只在开发阶段使用这个。

代码语言:txt
复制
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<Startup>()
                .Build();

            host.Run();
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2018-06-25 16:06:09

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100004963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档