【问题标题】:How to protect open/public Web API endpoints如何保护开放/公共 Web API 端点
【发布时间】:2017-06-14 11:50:05
【问题描述】:

我有几个 Web API 端点没有身份验证/授权,因为它也可以用于访客用户。这些端点将直接通过XHR/Ajax/JS 使用。但是,我想只允许来自几个来源的请求。为此,我使用了Cors 中间件,如下所示:

ConfigureServices 方法

services.AddCors(options =>
{
    options.AddPolicy("AllowSpecific", builder => 
        builder.WithOrigins("http://localhost:55476")
            .AllowAnyHeader()
            .AllowAnyMethod());
});

配置方法

app.UseCors("AllowSpecific");

此限制适用于来自浏览器的请求。但是,如果请求来自PostmanFiddler等Http客户端,则请求通过。

有没有办法解决这种情况?

【问题讨论】:

  • 身份验证或网络隔离。使呼叫者必须知道只有他们才能知道的事情,或者他们必须在物理上位于某个网络中才能拨打电话。或两者。在应用程序上或单独设置 IdentityServer 是一种选择。
  • @juunas 我真的不能使用身份验证/授权,因为它也必须对访客用户(B2C 环境)开放。如果 API 调用是从另一个服务器/mvc 控制器进行的,则可以使用 IP 地址进行限制。但是,请求将通过 Xhr/Ajax 直接来自 JS。
  • 添加一些身份验证
  • 添加基于承载令牌的身份验证(Jwt)
  • 如果您不能通过 IP 地址或添加身份验证进行限制,那么可悲的是,您唯一能做的就是 CORS。这可以防止网络浏览器从您不想要的域进行调用。但显然不会阻止以其他方式拨打的电话,因为 CORS 是一种君子协议。因此,您的 API 是公开的,无法阻止流量。例如,如果您担心有人拨打太多电话,那么您需要 rate 限制

标签: asp.net-core asp.net-core-webapi


【解决方案1】:

由于目前没有更好的选择,我已将 CORS 中间件替换为自定义中间件,该中间件将检查每个请求的标头 Origin 并根据配置允许/限制。这适用于跨浏览器请求和 HTTP 客户端请求。

中间件

public class OriginRestrictionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IConfiguration _configuration;
    private readonly ILogger _logger;

    public OriginRestrictionMiddleware(RequestDelegate next, IConfiguration configuration, ILoggerFactory loggerFactory)
    {
        _next = next;
        _configuration = configuration;
        _logger = loggerFactory.CreateLogger<OriginRestrictionMiddleware>();
    }

    public Task Invoke(HttpContext context)
    {
        try
        {
            var allowedOriginsConfig = _configuration.GetSection("AllowedOrigins").Value;

            var allowedOrigins = allowedOriginsConfig.Split(',');

            _logger.LogInformation("Allowed Origins: " + allowedOriginsConfig);

            var originHeader = context.Request.Headers.Where(h => h.Key == "Origin");
            if (originHeader.Any())
            {
                var requestOrigin = originHeader.First().Value.ToString();

                _logger.LogInformation("Request Origin: " + requestOrigin);

                foreach (var origin in allowedOrigins)
                {
                    //if(origin.StartsWith(requestOrigin))
                    if (requestOrigin.Contains(origin))
                    {
                        return _next(context);
                    }
                }
            }

            context.Response.StatusCode = 401;
            return context.Response.WriteAsync("Not Authorized");
        }
        catch(Exception ex)
        {
            _logger.LogInformation(ex.ToString());
            throw;
        }
    }
}

public static class OriginRestrictionMiddlewareExtension
{
    public static IApplicationBuilder UseOriginRestriction(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<OriginRestrictionMiddleware>();
    }
}

启动配置

app.UseOriginRestriction();

AppSettings.json

"AllowedOrigins": "http://localhost:55476,http://localhost:55477,chrome-extension"

chrome-extension 条目允许在开发期间来自Postman 的请求。部署到服务器时会被移除。

我怀疑这个解决方案也可以通过一种或另一种方式绕过。但是,我希望它适用于大多数情况。

【讨论】:

  • 我在 C# WebApi 项目 1 上创建 HttpClient,但是在另一个我有上述中间件的项目上,我没有得到任何带有密钥 "Origin"headers
猜你喜欢
  • 2020-03-28
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 2014-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
相关资源
最近更新 更多