Safari中的跨源资源共享策略拒绝跨源重定向

Safari中的跨源资源共享策略拒绝跨源重定向,safari,cors,Safari,Cors,我们有一个重定向到另一台服务器的api端点。它是通过XHR调用的,除了Safari(特别是在iOS上),它在大多数浏览器中都能正常工作 我在控制台中遇到的错误是: 跨源资源共享策略拒绝跨源重定向 我们在执行重定向的页面和另一台服务器上都有COR。重定向页面设置: Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: false 另一台服务器具有: Access-Control-Allow-Origin: * 如何在C

我们有一个重定向到另一台服务器的api端点。它是通过XHR调用的,除了Safari(特别是在iOS上),它在大多数浏览器中都能正常工作

我在控制台中遇到的错误是: 跨源资源共享策略拒绝跨源重定向

我们在执行重定向的页面和另一台服务器上都有COR。重定向页面设置:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: false
另一台服务器具有:

Access-Control-Allow-Origin: *
如何在CORS策略中允许重定向?

您需要设置“访问控制允许方法”标题


我在Heroku应用程序上托管API时遇到了类似的问题。在Chrome和Firefox上,从另一个域对我的API的请求工作得很好,但在Safari上,我遇到了令人沮丧的“跨源资源共享策略拒绝跨源重定向”

经过一些研究,似乎Safari中有一个错误,它阻止了CORS的一些重定向。我可以通过直接请求Heroku应用程序(
myapp.herokuapp.com/api
)而不是请求我的域(
mydomain.com/api
)来解决这个问题


如果您有一个可以重定向到API的设置,直接请求根域可能会有所帮助

如果您可以更改url,您可以在Apache上尝试使用代理传递配置。调用看起来像是在同一个域上,但它不会。 你试过了吗

Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: *

更多检查:

W3C规范和其他权威来源直接禁止通配符
访问控制允许源代码
访问控制允许凭据一起使用:true

注意:字符串“*”不能用于支持凭据的资源

重要注意事项:当响应认证请求时,服务器必须指定域,并且不能使用通配符

如果凭证模式为“包括”,则访问控制允许源站不能为
*

进一步步骤 因为你的问题缺乏细节,让我们做一些定义:

  • domain-a是客户端代码的域
  • domain-b是向其发出请求的端点的域
  • domain-c是请求最终重定向到的域
首先,我认为,你需要做一个变通办法。只要您告诉所有端点都在您的控制之下,那么您可以:

  • 从域a向域c发出直接请求(如果重定向取决于参数,甚至发出有条件的请求)
  • 在后端公开将请求包装到域b的另一个端点
如果一个bug真的违反了规范,那么向报告它也是很重要的。为了更容易地重现这个案例,我制作了一个CherryPy应用程序,你可以将它附加到报告中。运行它的步骤:

  • 将“127.0.0.1域-a域-b域-c”添加到您的
    /etc/hosts
  • 将以下代码放入
    corsredict.py
  • 在终端中运行这些命令

     virtualenv -p python3 venv
     . venv/bin/activate
     pip install cherrypy
     python corsredirect.py
    
  • 将浏览器指向并按下按钮

  • 这是应用程序

    #!/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)
    
    #/usr/bin/env蟒蛇3
    '''
    在/etc/hosts中为“domain-a”、“domain-b”、“domain-c”添加本地主机别名。
    流程是:[domain-a]--CORS-GET-->[domain-b]--redirect-->[domain-c]。
    开放为http://domain-a:8080/
    '''
    进口樱桃
    def cors():
    cherrypy.response.headers['Access-Control-Allow-Origin']='*'
    cherrypy.tools.cors=cherrypy.\u cptools.HandlerTool(cors)
    类应用程序:
    @樱桃树
    def索引(自):
    返回“”'
    CORS重定向测试
    请求
    document.querySelector('button')。onclick=function()
    {
    var xhr=new XMLHttpRequest();
    xhr.open('GET','http://domain-b:8080/redirect",对),;
    xhr.onload=函数()
    {
    var text=xhr.responseText;
    console.log('success',text);
    };
    xhr.onerror=函数()
    {
    控制台错误(“失败”);
    };
    xhr.send();
    };
    '''
    @樱桃树
    @cherrypy.config(**{'tools.cors.on':True})
    def重定向(自我):
    raise cherrypy.HTTPRedirect('http://domain-c:8080/endpoint')
    @樱桃树
    @cherrypy.config(**{'tools.cors.on':True})
    @cherrypy.tools.json_out()
    def端点(自身):
    返回{'answer':42}
    如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
    配置={
    “全球”:{
    'server.socket_host':'127.0.0.1',
    'server.socket_port':8080,
    “服务器线程池”:8
    }
    }
    cherrypy.quickstart(App(),“/”,config)
    
    对于除“简单请求”之外的任何内容,权威来源拒绝“访问控制允许来源”标题的通配符,并要求您显式设置标题“访问控制允许标题”

    以下是:

    唯一允许的方法是:

    • 得到
    • 职位
    除了用户代理自动设置的标题(例如。 连接、用户代理等),仅允许 可以手动设置的有:

    • 接受
    • 接受语言
    • 内容语言
    • 内容类型
    内容类型标题的唯一允许值为:

    • 应用程序/x-www-form-urlencoded
    • 多部分/表单数据
    • 文本/纯文本
    当您的请求不满足“简单请求”要求时,您可能会陷入困境

    除GET、HEAD或POST以外的其他方法。此外,如果POST用于发送内容类型不是application/x-www-form-urlencoded、multipart/form data或text/plain的请求数据,例如,如果POST请求使用application/XML或text/XML向服务器发送XML有效负载,则请求将被预引导

    至于证书
    #!/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)
    
    Access-Control-Request-Method: GET, OPTIONS
    Access-Control-Request-Headers: x-requested-with, Content-Type, CUSTOM-HEADER
    
    Access-Control-Allow-Origin: https://foo.example
    Access-Control-Allow-Methods: GET, OPTIONS
    Access-Control-Allow-Headers: x-requested-with, Content-Type, CUSTOM-HEADER