簡體   English   中英

Javascript-所請求的資源上沒有“ Access-Control-Allow-Origin”標頭

[英]Javascript - No 'Access-Control-Allow-Origin' header is present on the requested resource

我需要通過XmlHttpRequest將數據從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”標頭。 因此,不允許訪問原始“空”。

我應該如何解決? 我知道我需要使用一些“ Access-Control-Allow-Origin”標頭,但我不知道如何在此代碼中實現它。 順便說一句,我需要使用純JavaScript。

我用了flask-cors擴展名。

使用pip install flask-cors

那就是

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

這將允許所有域

舊問題,但是對於將來有這個問題的Google員工,我通過在我的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()

我使用此裝飾器將Javascript與Flask配合使用,並在可接受的方法列表中添加了“ OPTIONS”。 裝飾器應在路由裝飾器下面使用,如下所示:

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

編輯:鏈接似乎已損壞。 這是我使用的裝飾器。

from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper

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))
    # use str instead of basestring if using Python 3.x
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    # use str instead of basestring if using Python 3.x
    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

使用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 。添加以下內容:

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

實際上,Flask網站上有一個精彩的摘錄,用於修改服務器端的Access-Control-Allow-Origin標頭。 http://flask.pocoo.org/snippets/56/

您可以從這里輕松地進行操作,這是允許每個*域訪問您的URL,或在標頭中指定對URL的選擇。

來自MDN關於CORS的文章

在這種情況下,服務器將以Access-Control-Allow-Origin: *進行響應,這意味着該資源可以由任何域以跨站點的方式進行訪問。 如果位於http://bar.other的資源所有者希望僅從http://foo.example限制對資源的訪問 ,他們將發送回: Access-Control-Allow-Origin: http://foo.example

我使用了Zachary的解決方案。 效果很好。

對於那些想知道將新裝飾器放置在哪里的人:

只需從Zachary提供的鏈接中復制代碼,然后將其放在.py文件中即可

將其放在存在python模塊的文件夾中(根據您使用的系統以及是否使用虛擬環境而有所不同)。

在Flask應用中,從新創建的python模塊中導入方法crossdomain並使用它。

Access-Control-Allow-Origin必須由服務器而不是您發送。 當您調用另一個域時,瀏覽器將檢查服務器是否返回了此標頭。 如果不是,則呼叫失敗。 我不了解Python,所以我也不知道如何使您的服務器發送此標頭,甚至根本無法修改服務器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM