2013-04-26 52 views
9

我試圖讓Flask正確處理跨站點腳本。我從這裏採取了跨域的裝飾片段: http://flask.pocoo.org/snippets/56/Python燒瓶跨站點HTTP POST - 不適用於特定允許的來源

在下面的代碼中,我已經把裝飾片段和基本的燒瓶服務器。

我打電話給裝飾工程師headers ='Content-Type'因爲否則我得到「請求標頭字段內容類型不被Access-Control-Allow-Headers所允許」。在瀏覽器中。

所以這裏是我的問題: 原來,下面的代碼工作。但是,當我想限制只有特定的服務器,像這樣:

@crossdomain(origin='myserver.com', headers='Content-Type') 

我得到瀏覽器錯誤

「原產地http://myserver.com沒有被訪問控制允許來源允許的。」

我不能讓它爲除origin ='*'以外的其他任何工作。

有沒有人有任何想法?

下面是完整的代碼:

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

def crossdomain(origin=None, methods=None, headers=None, 
      max_age=21600, attach_to_all=True, 
      automatic_options=True): 
    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(): 
     if methods is not None: 
      return methods 

     options_resp = current_app.make_default_options_response() 
     return options_resp.headers['allow'] 

    def decorator(f): 
     def wrapped_function(*args, **kwargs): 
      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) 
      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 

app = Flask(__name__) 

@app.route('/my_service', methods=['POST', 'OPTIONS']) 
@crossdomain(origin='*', headers='Content-Type') 
def my_service(): 
    return jsonify(foo='cross domain ftw') 

if __name__ == '__main__': 
    app.run(host="0.0.0.0", port=8080, debug=True) 

僅供參考我的Python版本是2.7.2 瓶版本0.7.2

回答

2

我只是想用Python版本2.7.3相同的代碼和燒瓶版本0.8。

與這些版本,它失敗

@crossdomain(origin='myserver.com', headers='Content-Type') 

,但它與

@crossdomain(origin='http://myserver.com', headers='Content-Type') 

作品也許它只是不帶瓶0.7.2工作? (儘管它在片段頁面上說了什麼)。


編輯: 這個多很多(升級至0.9瓶)打後看來,真正的問題(或另一個問題)可能與具有在列表允許多個起源。換句話說,使用上面的代碼是這樣的:

@crossdomain(origin=['http://myserver.com', 'http://myserver2.com'], headers='Content-Type') 

不起作用。

要解決這個問題,我調整了裝飾器。在此處查看代碼: http://chopapp.com/#351l7gc3

此代碼只返回請求網站的域(如果它在列表中)。有點古怪,但至少對我來說,問題解決了:)

+0

不能看到代碼 – martriay 2013-10-28 19:06:27

+0

它的存在,但由於某種原因需要一些時間來加載。 – Nate 2013-10-28 19:57:50

+0

重新編寫代碼:注意request.headers ['Origin']可能是None,'in'運算符不能將None作爲左邊的參數。否則,謝謝:-) – 2016-03-20 21:49:21

0

Python正在努力防止你暴露自己跨站點腳本攻擊。

一個修復程序是通過放棄,並讓您的請求碰到運行燒瓶腳本的同一臺服務器。無論如何,從字符串中定義的遠程服務器獲取JSON是危險的業務。

我能夠讓瀏覽器本身保持在同一臺服務器上,這樣來解決它:

$('a#calculate').bind('click', function() { 
    $.getJSON('/_add_numbers', { 
    a: $('input[name="a"]').val(), 
    b: $('input[name="b"]').val() 
    }, function(data) { 
    $("#result").text(data.request); 
    }); 
    return false; 
}); 

注意如何的getJSON方法傳遞一個/_add_numbers。與瀏覽器通信以保持在同一主機上並查找該頁面。然後,瀏覽器是幸福的,安全的,我們住在同一主機上,你永遠不會得到錯誤:

Origin http://myserver.com is not allowed by Access-Control-Allow-Origin 
相關問題