我们有一个重定向到另一台服务器的api端点。它通过XHR调用,并且在大多数浏览器中都可以正常工作,除了Safari(特别是在iOS上)。
我在控制台中遇到的错误是: 跨源资源共享策略拒绝跨域重定向
我们在执行重定向的页面上和其他服务器上有CORS。重定向页面设置:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: false
另一台服务器有:
Access-Control-Allow-Origin: *
如何在CORS策略中允许重定向?
答案 0 :(得分:9)
W3C规范和其他权威来源在与Access-Control-Allow-Origin
一起使用时直接禁止使用通配符Access-Control-Allow-Credentials: true
。
注意:字符串“*”不能用于支持凭据的资源。
https://www.w3.org/TR/cors/#resource-requests
重要说明:在响应凭证请求时,服务器必须指定域,并且不能使用通配符。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials
如果凭据模式为“包含”,则
Access-Control-Allow-Origin
不能为*
。
https://fetch.spec.whatwg.org/#cors-protocol-and-credentials
因为你的问题缺乏细节,我们来做一些定义:
首先,我想,你想做一个解决方法。只要您告诉所有端点都在您的控制之下,那么您可以:
如果确实违反了规范,向WebKit tracker报告错误也很重要。为了更容易重现案例,我制作了一个CherryPy应用程序,您可以将其附加到报告中。运行它的步骤:
/etc/hosts
corsredirect.py
在终端
中运行这些命令 virtualenv -p python3 venv
. venv/bin/activate
pip install cherrypy
python corsredirect.py
将浏览器指向http://domain-a:8080并按下按钮
有应用程序。
#!/usr/bin/env python3
'''
Add localhost aliases in /etc/hosts for "domain-a", "domain-b", "domain-c".
The flow is: [domain-a] --CORS-GET--> [domain-b] --redirect--> [domain-c].
Open as http://domain-a:8080/
'''
import cherrypy
def cors():
cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'
cherrypy.tools.cors = cherrypy._cptools.HandlerTool(cors)
class App:
@cherrypy.expose
def index(self):
return '''<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=utf-8' http-equiv='content-type'>
<title>CORS redirect test</title>
</head>
<body>
<button>make request</button>
<script type='text/javascript'>
document.querySelector('button').onclick = function()
{
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain-b:8080/redirect', true);
xhr.onload = function()
{
var text = xhr.responseText;
console.log('success', text);
};
xhr.onerror = function()
{
console.error('failure');
};
xhr.send();
};
</script>
</body>
</html>
'''
@cherrypy.expose
@cherrypy.config(**{'tools.cors.on': True})
def redirect(self):
raise cherrypy.HTTPRedirect('http://domain-c:8080/endpoint')
@cherrypy.expose
@cherrypy.config(**{'tools.cors.on': True})
@cherrypy.tools.json_out()
def endpoint(self):
return {'answer': 42}
if __name__ == '__main__':
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}
cherrypy.quickstart(App(), '/', config)
答案 1 :(得分:1)
您需要设置“Access-Control-Allow-Methods”标题。
Access-Control-Allow-Methods: *
答案 2 :(得分:1)
我遇到了在Heroku应用上托管我的API的类似问题。在Chrome和Firefox上,来自其他域的对我的API的请求工作得很好,但在Safari上,我遇到了令人沮丧的跨越源重定向被跨域资源共享策略拒绝了#34;。
经过一番研究后,似乎Safari中可能有一个bug阻止了一些使用CORS的重定向。我通过直接(myapp.herokuapp.com/api
)而不是我的域(mydomain.com/api
)请求Heroku应用程序来解决这个问题。
如果您的设置中有重定向到您的API,请直接请求根域可能有所帮助。
答案 3 :(得分:1)
如果您可以更改您的网址,您可以尝试使用Apache上的代理传递配置。该呼叫看起来像是在同一个域上但不会。 https://httpd.apache.org/docs/current/fr/mod/mod_proxy.html
答案 4 :(得分:1)
你试过吗?
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: *
如需更多检查:http://enable-cors.org/
答案 5 :(得分:0)
除了&#34;简单请求&#34;以外的任何其他内容,权威来源拒绝使用#34; Access-Control-Allow-Origin&#34;标题并要求您明确设置标题&#34; Access-Control-Allow-Headers&#34;。
以下是Mozilla states for "Simple request":
唯一允许的方法是:
- GET
- HEAD
- POST
除了用户代理自动设置的标头(例如 连接,用户代理等),允许的唯一标头 手动设置是:
- 接受
- 接受语言
- 内容的语言
- 内容类型
Content-Type标头唯一允许的值是:
- 应用程序/ x-WWW窗体-urlencoded
- 的multipart / form-data的
- 文本/纯
当您的请求未满足&#34;简单请求&#34;要求你可能属于"Preflighted Requests"。
GET,HEAD或POST以外的方法。此外,如果使用POST来发送具有除application / x-www-form-urlencoded,multipart / form-data或text / plain之外的Content-Type的请求数据,例如,如果POST请求使用application / xml或text / xml向服务器发送XML有效负载,则该请求将被预检。
至于有资格的请求 -
重要说明:在响应凭证请求时,服务器必须指定域,并且不能使用通配符。 Access-Control-Allow-Origin:*
由于您没有提供来自您的网页和服务器的实际HTTP请求和响应,因此我必须做出一些假设。我假设您的网页已在域foo.example下加载,并且您的API位于相同的foo.example域下,并且您的&#34;其他&#34;服务器位于域bar.example上。
您可能需要设置自己的页面,以便向&#34;其他人提供重定向请求。带有这些标题的服务器:
Access-Control-Request-Method: GET, OPTIONS
Access-Control-Request-Headers: x-requested-with, Content-Type, CUSTOM-HEADER
然后你可能需要设置你的&#34;其他&#34;服务器响应选项请求:
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: x-requested-with, Content-Type, CUSTOM-HEADER
然后您的页面应该能够完成请求。
答案 6 :(得分:0)
在两台服务器上启用HTTPS已经解决了我的问题。