簡體   English   中英

Ajax POST 調用被 ASP NET Web API 的 CORS 阻止 - 對預檢請求的響應未通過訪問控制檢查

[英]Ajax POST call blocked by CORS from ASP NET Web API - Response to preflight request doesn't pass access control check

問題總結:

我有兩個托管在不同域中的 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標頭。

看看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 報告,您可以每天收到電子郵件,而不會在用戶收到郵件時被郵件淹沒阻止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM