请求的资源上不存在“Access-Control-Allow-Origin”标头 + 响应的 HTTP 状态代码为 401

Posted

技术标签:

【中文标题】请求的资源上不存在“Access-Control-Allow-Origin”标头 + 响应的 HTTP 状态代码为 401【英文标题】:No 'Access-Control-Allow-Origin' header is present on the requested resource + The response had HTTP status code 401 【发布时间】:2017-10-14 20:24:49 【问题描述】:

XMLHttpRequest 无法加载 http://192.168.1.253:8080/... 否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:4200” 使用权。响应的 HTTP 状态代码为 401。

很常见的错误,有很多可能的解决方案都没有奏效。我了解(我认为)CORS 应该如何工作,并且我没有发现我的 HTTP 标头有任何问题,但它仍然无法正常工作

来自 Chrome:

Request URL:http://192.168.1.253:8080/...
Request Method:OPTIONS
Status Code:200 OK
Remote Address:192.168.1.253:8080
Referrer Policy:no-referrer-when-downgrade
Response Headers
Access-Control-Allow-Headers:x-requested-with,accept,content-
type,authorization
Access-Control-Allow-Methods:POST, GET, PUT, PATCH, OPTIONS, DELETE
Access-Control-Allow-Origin:*
Access-Control-Max-Age:3600
Allow:GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Connection:keep-alive
Content-Length:0
Date:Mon, 15 May 2017 21:50:55 GMT
Expires:0
Pragma:no-cache
Server:...
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization,content-type
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:192.168.1.253:8080
Origin:http://localhost:4200
Pragma:no-cache
Referer:http://localhost:4200/...
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 
(Khtml, like Gecko) Chrome/57.0.2987.133 Safari/537.36

我的理解是 OPTIONS 响应需要 Access-Control-Allow-Origin 标头集并允许方法类型和标头值,它确实如此

下面的相关角度。我已经做了很多不同的组合,标题中有各种不同的东西,但没有任何效果

private getObject<T>(path: string): Promise<T> 
    return this.http.get(SERVER_URL + path, this.authenticationToken())
        .toPromise()
        .then(response => response.json() as T)
        .catch(this.handleError);


private authenticationToken() : RequestOptions 
    let login = JSON.parse(sessionStorage.getItem('currentLogin'));
    if (login && login.authenticationToken) 
        let headers = new Headers( 
            'Authorization': 'Basic ' + login.authenticationToken,
            'Content-type': 'application/json', 
          );
        return new RequestOptions( headers: headers );
    

我感觉我遗漏了一些明显的东西,但这让我发疯了,感谢任何帮助。请注意,这确实适用于预先存在的 Ember 应用程序,所以我认为它不是服务器

【问题讨论】:

当您尝试 Access-Control-Allow-Origin:localhost:4200 - 明确输入 url 而不是 * - 是否有效? 这实际上不是您的前端或您的请求。您的 backend 需要配置为允许 CORS 访问。你得到的实际上是 Chrome 的一项安全措施。我并不是说它会解决你所有的问题(401),但在你弄清楚如何在后端配置 CORS 之前,这是一个很好的扩展来告诉 Chrome 关闭:chrome.google.com/webstore/detail/allow-control-allow-origi/… @Eeks33 怕不是 @joh04667 感谢插件,虽然我不明白它如何成为后端,因为它可以与不同的应用程序一起使用 由于这与后端服务器有关,因此您需要识别它运行的技术并相应地发布/标记。 Angular 代码只是客户端请求,因此与 CORS 无关 【参考方案1】:

响应的 HTTP 状态代码为 401。

401 表示身份验证错误。问题中的错误消息不是来自预检OPTIONS 请求的响应。相反,它似乎是针对您尝试发送的实际 GET 请求。

因此,根据该错误消息,最有可能的情况是浏览器的预检 OPTIONS 请求成功,但您的 GET 请求由于身份验证失败而未成功。

所以服务器返回一个 401 响应/错误页面。并且许多/大多数 Web 服务器未配置为发送 Access-Control-Allow-Origin 响应标头以获取错误响应/页面。这也是您收到有关该标头丢失的消息的唯一原因。

但是错误响应缺少的标头不是问题的原因;相反,401 是。

因此,您似乎想找出导致服务器发送 401 响应的原因——为什么您会遇到身份验证失败。如果您解决了这个问题,您可能会收到来自服务器的响应,其中包含预期的 Access-Control-Allow-Origin 响应标头。

【讨论】:

【参考方案2】:

这是我们在使用 Angular 和 Ionic 时发现的典型错误,出现问题是因为当您的应用在您的应用的浏览器中加载时,会加载来自本地的 origin 的所有内容地址@987654321@,然后当你想将任何AJAX请求发送到另一个主机而不是 localhost:4200 时,该请求从不同于origin的任何点调用,它需要一个CORS(Cross Origin Resource Sharing)预检请求,看看它是否可以访问资源。

解决方案是使用 Proxy To Backend,这样您就可以劫持某些 url 并将它们发送到后端服务器。实现很简单:

1.- 在项目的根文件夹中创建一个文件proxy.conf.js

2.- 配置你的代理,在你的 proxy.conf.js 文件里放这个,假设你的新主机在 @987654322@

const PROXY_CONFIG = [
    
        context: [
            "/my",
            "/many",
            "/endpoints",
            "/i",
            "/need",
            "/to",
            "/proxy"
        ],
        target: "http://localhost:3000",
        secure: false
    
]

module.exports = PROXY_CONFIG;

3.- 修改您的 package.json 文件,插入此 "start": "ng serve --proxy-config proxy.conf.js",

4.- 在您的服务中,将您的请求路径从 @987654323@ 更改为 ../endpoints/any/path/that/you/use(假设另一个主机在 localhost:3000 并且上下文是 /endpoints)。

5.- 从根文件夹开始运行 Angular: npm start ;这将使用代理参数执行 ng serve

如果您需要更多相关信息,请查看Proxy to backend Angular Cli documentation

【讨论】:

请不要对多个问题发布相同的答案。发布一个好的答案,然后投票/标记以关闭其他问题作为重复问题。如果问题不是重复的,调整您对该问题的回答。 为什么这一行有 .js 而不是 .json ? - 3.- 修改你的 package.json 文件,插入这个“开始”:“ng serve --proxy-config proxy.conf.js”, 这是一个“js”文件,因为配置是通过模块导出导出的,node js 在运行“start”脚本时将此配置解释为常量。

以上是关于请求的资源上不存在“Access-Control-Allow-Origin”标头 + 响应的 HTTP 状态代码为 401的主要内容,如果未能解决你的问题,请参考以下文章

django中的“请求的资源上不存在'Access-Control-Allow-Origin'标头”

如何解决请求的资源上不存在“Access-Control-Allow-Origin”标头

Http.post 请求的资源上不存在“Access-Control-Allow-Origin”标头

请求的资源发布请求上不存在“Access-Control-Allow-Origin”标头

Angular 2请求的资源上不存在“Access-Control-Allow-Origin”标头[重复]

API 请求错误 - 请求的资源上不存在“Access-Control-Allow-Origin”标头