发出 HTTP 请求时出现 cross-origin 错误
I get a cross-origin error when making a HTTP requests
当我从浏览器发出请求时,我的请求是有效的,但是通过 Angular 9 应用程序我收到 401 错误。
这是来自 chrome 的 header:
Request URL: http://localhost:1234/api/Common/GetMy_List
Request Method: GET
Status Code: 401
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, X-Token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Allow-Origin: *
Cache-Control: private
Content-Length: 6069
Content-Type: text/html; charset=utf-8
Date: Wed, 06 Oct 2021 12:55:39 GMT
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: localhost:1234
Origin: http://localhost:4200
Referer: http://localhost:4200/
sec-ch-ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36
我有一个 angular 9 项目,其中 proxy.conf.json 文件在 package.json 中声明。
该文件包含以下行:
{
"/api/*": {
"target": "http://localhost:1234",
"secure": true,
"logLevel": "debug",
"changeOrigin": true
}
}
在服务器端有一个 asp.net api global.asax:
public void Application_BeginRequest(object sender, EventArgs e)
{
string httpOrigin = Request.Params["HTTP_ORIGIN"];
if (httpOrigin == null) httpOrigin = "*";
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 200;
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
在web.config中:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<directoryBrowse enabled="false" />
</system.webServer>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonateBehaviour">
<clientCredentials>
<windows allowedImpersonationLevel="Delegation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" maxReceivedMessageSize="2147483647">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/xxx.svc" behaviorConfiguration="ImpersonateBehaviour" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="Service1Ref.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
浏览器允许对来源的任何 http 请求(url 您的 http session 开始的地方)。在单页应用程序中,我们通常加载 DOM which intern makes additional XHRs to a new domain (usually a new web app/rest api)。这被认为是一个安全漏洞,所有知名的现代浏览器都停止支持这种行为。
为了缓解这种情况,您需要在源域中使用代理。所有获取数据的请求都应该通过它。
在 angular 你可以:
- 配置服务器以发送适当的 CORS headers
- 配置Angular CLI 代理
我建议使用 angular CLI 代理而不是添加 CORS 配置。
尝试将您的 Application_BeginRequest
更改为此。当我尝试使用你的代码时,它在我的代码上失败了。以下代码有效。
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
HttpContext.Current.Response.End();
}
}
我注意到我可以输入 Application_BeginRequest 但不能输入我在控制器中的函数,这意味着 CORES 权限问题。
所以在 IIS 中,我添加了匿名身份验证,现在我可以向 GET/POST 和其他人发出请求。
在 IIS 的“站点”中选择您的站点,然后双击“身份验证”类别,然后=>:
当我从浏览器发出请求时,我的请求是有效的,但是通过 Angular 9 应用程序我收到 401 错误。 这是来自 chrome 的 header:
Request URL: http://localhost:1234/api/Common/GetMy_List
Request Method: GET
Status Code: 401
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, X-Token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Allow-Origin: *
Cache-Control: private
Content-Length: 6069
Content-Type: text/html; charset=utf-8
Date: Wed, 06 Oct 2021 12:55:39 GMT
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: localhost:1234
Origin: http://localhost:4200
Referer: http://localhost:4200/
sec-ch-ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36
我有一个 angular 9 项目,其中 proxy.conf.json 文件在 package.json 中声明。 该文件包含以下行:
{
"/api/*": {
"target": "http://localhost:1234",
"secure": true,
"logLevel": "debug",
"changeOrigin": true
}
}
在服务器端有一个 asp.net api global.asax:
public void Application_BeginRequest(object sender, EventArgs e)
{
string httpOrigin = Request.Params["HTTP_ORIGIN"];
if (httpOrigin == null) httpOrigin = "*";
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 200;
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
在web.config中:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<directoryBrowse enabled="false" />
</system.webServer>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonateBehaviour">
<clientCredentials>
<windows allowedImpersonationLevel="Delegation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" maxReceivedMessageSize="2147483647">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/xxx.svc" behaviorConfiguration="ImpersonateBehaviour" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="Service1Ref.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
浏览器允许对来源的任何 http 请求(url 您的 http session 开始的地方)。在单页应用程序中,我们通常加载 DOM which intern makes additional XHRs to a new domain (usually a new web app/rest api)。这被认为是一个安全漏洞,所有知名的现代浏览器都停止支持这种行为。
为了缓解这种情况,您需要在源域中使用代理。所有获取数据的请求都应该通过它。
在 angular 你可以:
- 配置服务器以发送适当的 CORS headers
- 配置Angular CLI 代理
我建议使用 angular CLI 代理而不是添加 CORS 配置。
尝试将您的 Application_BeginRequest
更改为此。当我尝试使用你的代码时,它在我的代码上失败了。以下代码有效。
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
HttpContext.Current.Response.End();
}
}
我注意到我可以输入 Application_BeginRequest 但不能输入我在控制器中的函数,这意味着 CORES 权限问题。
所以在 IIS 中,我添加了匿名身份验证,现在我可以向 GET/POST 和其他人发出请求。
在 IIS 的“站点”中选择您的站点,然后双击“身份验证”类别,然后=>: