来自 ASP NET Web API 的 CORS 阻止 Ajax POST 调用 - 对预检请求的响应未通过访问控制检查

Posted

技术标签:

【中文标题】来自 ASP NET Web API 的 CORS 阻止 Ajax POST 调用 - 对预检请求的响应未通过访问控制检查【英文标题】:Ajax POST call blocked by CORS from ASP NET Web API - Response to preflight request doesn't pass access control check 【发布时间】:2020-06-24 10:35:48 【问题描述】:

问题总结:

我有两个托管在不同域中的 Web 项目。在对我的 Web API 项目进行 ajax 调用时,我得到以下信息:

CORS 已阻止从源 '' 访问 '' 处的 XMLHttpRequest 策略:对预检请求的响应未通过访问控制 检查:没有“Access-Control-Allow-Origin”标头出现在 请求的资源。


第一个项目 - Web API

我的第一个项目,即 ASP NET Web API (.Net Framework 4.8)

我为所有人全局启用了 CORS,只是为了确保测试正确通过。 在我的WebApiConfig 文件中,我有以下行。

config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

上面有using System.Web.Http.Cors;

我的方法没有什么特别的属性,因为我们全局启用了 CORS。

[RoutePrefix("api/Test")]
public class TestController : ApiController

    [Route("RequestConnection")]
    [HttpPost]
    public IHttpActionResult RequestConnection(MasterOnRequestInputModel inputModel)
    
        ...some code logic here...
    


第二个项目 - 带有 AJAX 请求的 javascript

我的第二个项目想在 Web API 中调用上述方法。

我的 ajax 调用如下所示:

$.ajax(
    type: "POST",
    url: myUrl,
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    data: 
        'Body': body,
        'Head': head,
        'Width': width,
        'Height': height
    ,
    success: screencastControllerPostSuccess
);

在 Chrome 中,请求如下所示:

我做错了什么?


编辑:

回答

如果你们这样做了,正如上面所写的那样,你应该对 CORS 绝对没有问题。

我的问题是我们公司正在使用的WAF。 WAF 拒绝了我的请求,因为它是潜在的攻击。这是因为我在请求正文中发送 html 元素。我们与我的系统管理员同事一起解决了这个问题。

所以有趣的部分是,在我的请求被 WAF 拒绝后,它返回一个错误,就好像问题出在 CORS 上一样。那是因为请求确实是跨域的,但是拒绝请求后的 WAF 通用响应没有Access-Control-Allow-Origin 标头。

【问题讨论】:

“跨域”服务器是否处理“OPTIONS”请求?这就是飞行前的意义 是的,确实如此。我在想我在 ASP 网络控制器中遗漏了一些东西。或者可能是 ajax 中的一些标题? 很明显,因为 OPTIONS 响应标头缺少所需的访问控制标头 In Chrome the request looks as follow: - response 标头是什么样的 - 请求标头不是问题 它没有。 Failed to load response data 【参考方案1】:

看看www.asp-waf.com 的 WAF,你会发现它很容易处理,也很容易发现类似的问题,因为你只需注册 OnGuardAction 事件,你就可以看到它会被阻止的内容和原因调试它或将其发送到日志。

我们通过像这样使用基类 FireWallBase 来做到这一点

public class MyFireWall : FireWallBase

    private readonly ILogger<MyFireWall> _logger;
    private bool _agreeWithFirewall = true;

    public MyFireWall(
        //enable accessing AppConfig
        IConfiguration configuration

        //allow DI to provide interfaces to base class
        , ILoggerFactory? loggerFactory = null, IMemoryCache? memoryCache = null
        , IIncidentDatabase? incidentDatabase = null, IWhoisRepository? whoisRepository = null, ISubscriptionsRepository? subscriptions = null
        , IEmailReportDesination? emailReportDesination = null, IDatabaseReportDestination? databaseReportDestination = null
        , ILoggerReportDesination? loggerReportDestination = null, IFireWallDiskLoggerDestination? diskLoggerDestination = null
        , IEventLogReporting? eventLogReporting = null, IGeoFactory? geoFactory = null, ILatLongRepository? latLongRepository = null
        , IResetRepository? resetRepository = null)
        : base(loggerFactory, memoryCache, incidentDatabase, whoisRepository, subscriptions, emailReportDesination, databaseReportDestination
              , loggerReportDestination, diskLoggerDestination, eventLogReporting, geoFactory, latLongRepository, resetRepository)
    
        var section = configuration.GetSection("FireWall");
        if (section.Exists())
        
            _isReccommendOnly = section.GetValue<bool>("AgreeWithFirewall");
        
        base.Trigger_OnFireWallCreated(this);
        OnIncident += MyFireWall_OnIncident;
        OnGuardAction += MyFireWall_OnGuardAction;
        OnUserTypeChange += MyFireWall_OnUserTypeChange;
        _logger = loggerFactory.CreateLogger<MyFireWall>();
    


    private void MyFireWall_OnUserTypeChange(object? sender, Walter.Web.FireWall.EventArguments.UserTypeChangedEventArgs e)
    
        _logger?.LogCritical("oldType : newType\n   route\n   Rules:\n   data"
            , e.OriginalType
            , e.NewType
            , e.Rout
            , string.Join("\n   ", e.Rules)
            );

        //allow the change
        e.Allow = true;

        if (e.OriginalType.HasFlag(UserTypes.IsSearchEngine) && e.NewType.HasFlag(UserTypes.IsMalicious))
        
            //remove the malicious flag from search engines to not prevent search engines from 
            //indexing the site
            e.NewType &= ~UserTypes.IsMalicious;
        
    

    private void MyFireWall_OnGuardAction(object? sender, Walter.Web.FireWall.EventArguments.GuardActionEventArgs e)
    
        _logger?.LogCritical("Method page : route\n   action:RuleNr\n   Reasons:Reason\n   data"
            , e.Page.Method
            , e.Page.OriginalUrl.AbsolutePath
            , e.Page.FireWallRoute
            , e.Action
            , string.Join("\n   ", e.Page.PageViolationStack.Select(s => s.ToString()))
            );

        //allow the firewall to block requests
        e.Allow = _agreeWithFirewall;
    

    private void MyFireWall_OnIncident(object? sender, Walter.Web.FireWall.EventArguments.FireWallIncidentEventArgs e)
    
        _logger?.LogCritical("Method page : route\n   rule:RuleNr\n   Reasons:Reason\n   data"
            , e.Page.Method
            , e.Page.OriginalUrl.AbsolutePath
            , e.Page.FireWallRoute
            , e.StackEntry.Rule
            , e.StackEntry.RuleNr
            , e.StackEntry.Reason
            , string.Join("\n   ", e.Data.Select(s => $"s.Key:s.Value"))
            );
        //allow the firewall to raise incidents
        e.Allow = _agreeWithFirewall;
    

我们通过依赖注入启用防火墙,就像 .net Web 应用程序中的其他所有功能一样。我可以像这样使用它来启用我自己的防火墙类:

services.AddFireWall<MyFireWall>("Token", "Key", new Uri(Configuration["domainUri"], UriKind.Absolute), options =>
         //add your options here
       );

在选项中,您可以在 options.Rules.Headers 下配置 CORS,但您可以做的远不止这些。

防火墙在我的 NuGet 包中 Walter.Web.FireWall.* 有很多附加组件,例如地理以及使用时间跨度定时向 SMTP 报告,您可以每天收到电子邮件,而不会在用户被阻止时被邮件淹没.

【讨论】:

看看asp-waf.com/download/ASP-WAF-FireWall-Getting-Started.pdf

以上是关于来自 ASP NET Web API 的 CORS 阻止 Ajax POST 调用 - 对预检请求的响应未通过访问控制检查的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net WEB API 2.0 - CORS

通过微软的cors类库,让ASP.NET Web API 支持 CORS

我正在将我的 asp.net web api 迁移到 asp.net core。 Cors 迁移

asp.net web api 2 CORS 和身份验证授权配置

CORS 不适用于 ASP NET 5 Web Api

向 ASP.NET Web API 发送请求时出现 CORS 错误