首页 文章

Javascript - 请求的资源上没有'Access-Control-Allow-Origin'标头

提问于
浏览
36

我需要通过XavascriptHttpRequest从javascript向python服务器发送数据 . 因为我使用的是localhost,所以我需要使用CORS . 我正在使用Flask框架及其模块flask_cors . 作为javascript我有这个:

var xmlhttp;
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    }
    else {// code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.open("POST", "http://localhost:5000/signin", true);
    var params = "email=" + email + "&password=" + password;


    xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
        if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            alert(xmlhttp.responseText);
        }
    }
    xmlhttp.send(params);

和python代码:

@app.route('/signin', methods=['POST'])
@cross_origin()
def sign_in():
    email = cgi.escape(request.values["email"])
    password = cgi.escape(request.values["password"])

但是当我执行它时,我得到了这样的信息:

XMLHttpRequest无法加载localhost:5000 / signin . 请求的资源上不存在“Access-Control-Allow-Origin”标头 . 因此不允许原点'null'访问 .

我应该怎么解决?我知道我需要使用一些“Access-Control-Allow-Origin”标头,但我不知道如何在此代码中实现它 . 顺便说一句,我需要使用纯JavaScript .

7 回答

  • 6

    我通过使用decorator让Flask与Flask一起工作,并将"OPTIONS"添加到我接受的方法列表中 . 应该在路径装饰器下面使用装饰器,如下所示:

    @app.route('/login', methods=['POST', 'OPTIONS'])
    @crossdomain(origin='*')
    def login()
        ...
    

    Edit: 链接似乎被破坏了 . 这是我用过的装饰器 .

    def crossdomain(origin=None, methods=None, headers=None, max_age=21600,
                    attach_to_all=True, automatic_options=True):
        """Decorator function that allows crossdomain requests.
          Courtesy of
          https://blog.skyred.fi/articles/better-crossdomain-snippet-for-flask.html
        """
        if methods is not None:
            methods = ', '.join(sorted(x.upper() for x in methods))
        if headers is not None and not isinstance(headers, basestring):
            headers = ', '.join(x.upper() for x in headers)
        if not isinstance(origin, basestring):
            origin = ', '.join(origin)
        if isinstance(max_age, timedelta):
            max_age = max_age.total_seconds()
    
        def get_methods():
            """ Determines which methods are allowed
            """
            if methods is not None:
                return methods
    
            options_resp = current_app.make_default_options_response()
            return options_resp.headers['allow']
    
        def decorator(f):
            """The decorator function
            """
            def wrapped_function(*args, **kwargs):
                """Caries out the actual cross domain code
                """
                if automatic_options and request.method == 'OPTIONS':
                    resp = current_app.make_default_options_response()
                else:
                    resp = make_response(f(*args, **kwargs))
                if not attach_to_all and request.method != 'OPTIONS':
                    return resp
    
                h = resp.headers
                h['Access-Control-Allow-Origin'] = origin
                h['Access-Control-Allow-Methods'] = get_methods()
                h['Access-Control-Max-Age'] = str(max_age)
                h['Access-Control-Allow-Credentials'] = 'true'
                h['Access-Control-Allow-Headers'] = \
                    "Origin, X-Requested-With, Content-Type, Accept, Authorization"
                if headers is not None:
                    h['Access-Control-Allow-Headers'] = headers
                return resp
    
            f.provide_automatic_options = False
            return update_wrapper(wrapped_function, f)
        return decorator
    
  • 2

    我使用了 flask-cors 扩展名 .

    使用 pip install flask-cors 安装

    那就简单了

    from flask_cors import CORS
    app = Flask(__name__)
    CORS(app)
    

    这将允许所有域

  • 0

    老问题,但对于有这个问题的未来googlers,我通过将以下内容添加到我的app.py文件中来解决它(以及与CORS有关的一些其他下游问题)

    app = Flask(__name__)
    api = Api(app)
    
    @app.after_request
    def after_request(response):
      response.headers.add('Access-Control-Allow-Origin', '*')
      response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
      response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
      return response
    
    
    if __name__ == '__main__':
        app.run()
    
  • 28

    使用python 2.7时

    app = Flask(__name__)
    api = Api(app)
    
    @app.after_request
    def after_request(response):
      response.headers.add('Access-Control-Allow-Origin', '*')
      response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
      response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
      return response
    
    
    if __name__ == '__main__':
        app.run()
    

    在python3或者前面运行时,使用命令 pip install flask-cors 安装flask-cors . 添加以下内容:

    from flask_cors import CORS
    app = Flask(__name__)
    CORS(app)
    
  • 38

    Flask网站上实际上有一个很棒的片段来修改 Access-Control-Allow-Origin 标头服务器端 . http://flask.pocoo.org/snippets/56/

    您可以轻松地从那里开始,即允许每个 * 域访问您的URL,或在 Headers 内指定您选择的URL .

    来自MDN's article on CORS

    在这种情况下,服务器以Access-Control-Allow-Origin:*响应,这意味着任何域都可以跨站点方式访问资源 . 如果http://bar.other的资源所有者希望将对资源的访问限制为仅来自http://foo.example,则他们将发回:Access-Control-Allow-Origin:http:// foo . 例 .

  • 56

    我使用了Zachary的解决方案 . 效果很好 .

    对于那些想知道放置新装饰器的人:

    只需从Zachary提供的链接中复制代码并将其放在 .py 文件中即可

    将它放在python模块所在的文件夹中(根据您使用的系统以及您是否使用虚拟环境而有所不同) .

    在您的烧瓶应用程序中,从新创建的python模块导入方法 crossdomain 并使用它 .

  • 13

    Access-Control-Allow-Origin必须由服务器发送,而不是由您发送 . 当您调用另一个域时,浏览器会检查服务器是否返回此标头 . 如果它不知道Python,那么我不知道如何让你的服务器发送这个头,或者即使你可以修改服务器 .

相关问题