[英]Angular POST request been blocked by CORS policy: Response to preflight request doesn't pass access control check
[英]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”標頭。
我的第一個項目,是 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...
}
}
我的第二個項目想在 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.