2017-06-13 76 views
1

我有几个Web API端点没有身份验证/授权,因为它也可以用于访客用户。这些终点将通过XHR/Ajax/JS直接消耗。但是,我想只允许来自几个来源的请求。对于这一点,我已经使用像下面的Cors中间件:如何保护开放/公共Web API端点

ConfigureServices方法

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

配置方法

app.UseCors("AllowSpecific"); 

此限制适用于从浏览器的未来需求。但是,如果请求来自Http客户端,例如Postman,Fiddler等,请求就会通过。

有没有解决这种情况的方法?

+0

身份验证或网络隔离。使其成为呼叫者必须知道的东西,只有他们能够知道,或者他们必须身处某个网络才能打电话。或两者。在应用程序上或单独设置IdentityServer是一种选择。 – juunas

+1

@juunas我真的不能使用认证/授权,因为它必须为来宾用户(B2C环境)开放。如果API调用是从另一个服务器/ mvc控制器创建的,则可以使用IP地址进行限制。然而,请求将直接来自JS通过Xhr/Ajax。 –

+0

添加一些验证 –

回答

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在开发过程中发出请求。它将在部署到服务器时被删除。

我怀疑这种解决方案也可以绕过这种或那种方式。不过,我希望它能适用于大多数情况。