发出 HTTP 请求时出现跨域错误

Posted

技术标签:

【中文标题】发出 HTTP 请求时出现跨域错误【英文标题】:I get a cross-origin error when making a HTTP requests 【发布时间】:2021-11-26 15:53:38 【问题描述】:

当我从浏览器发出请求时,我的请求有效,但通过 Angular 9 应用程序我收到 401 错误。 这是来自 chrome 的标题:

    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 项目,其中包含在 package.json 中声明的 proxy.conf.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>

【问题讨论】:

有人在这里吗?? 尝试添加此标头Access-Control-Expose-Headers: * - 可以吗? 【参考方案1】:

尝试将您的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();
    

【讨论】:

【参考方案2】:

浏览器允许任何对源的 http 请求(您的 http 会话开始的 url)。在单页应用程序中,我们通常会加载 DOM,实习生会向新域(通常是新的 Web 应用程序/rest api)添加额外的 XHR。这被认为是一个安全漏洞,所有知名的现代浏览器都不再支持这种行为。

为了缓解这种情况,您需要在源域中使用代理。所有获取数据的请求都应该通过它。

在角度你可以:

    配置服务器以发送适当的 CORS 标头 配置 Angular CLI 代理

我建议使用 Angular CLI 代理而不是添加 CORS 配置。

【讨论】:

在我的回答中我写道我声明了 proxy.conf.json。是这个意思吗? 是的,您的 API 网址是什么?我猜它在本地主机上,而不是在与您的网络相同的端口上。然后,您可能必须将其更改为“目标”:“http://>”,如果您在多个端点中部署了 api,那么也有一种方法可以处理它。请参阅:angular.io/guide/build#proxy-multiple-entries API 网址:localhost:1234。请阅读我的代码【参考方案3】:

我注意到我可以进入 Application_BeginRequest 但不能进入控制器中的函数,这意味着 CORES 权限问题。

所以在 IIS 中,我添加了匿名身份验证,现在我可以发出 GET/POST 和其他请求。

在 IIS 中,在 Sites 中选择您的站点,然后双击 Authentications 类别,然后=>:

【讨论】:

以上是关于发出 HTTP 请求时出现跨域错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 .getJSON 获取 Play 商店应用详细信息时出现跨域阻止请求 [CORS] 错误

将应用程序移动到子域时出现跨域安全错误 (2018)

跨域问题和django中实现跨域

tomcat8.5.30+ 配置跨域问题

尝试使用 SolidWorks VBA 发出 HTTP 请求时出现奇怪的错误

Vue 中dev上实现跨域请求