2014-03-04 1 views
24

자바 스크립트에서 Python 서버로 XmlHttpRequest를 통해 데이터를 보내야합니다. localhost를 사용하기 때문에 CORS를 사용해야합니다. 나는 플라스크 프레임 워크와 그의 모듈 flask_cors를 사용하고 있습니다.Javascript - 요청한 리소스에 'Access-Control-Allow-Origin'헤더가 없습니다.

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); 

및 파이썬 코드 : 자바 스크립트로 나는이 가지고

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

하지만 난 그것을 실행할 때이 메시지가 얻을 것이다 :

XMLHttpRequest cannot load localhost:5000/signin. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

내가 그것을 해결하는 방법을? "Access-Control-Allow-Origin"헤더를 사용해야한다는 것을 알고 있지만이 코드에서 구현하는 방법을 모르겠습니다. 그건 그렇고 순수한 자바 스크립트를 사용해야합니다. 고맙습니다.

답변

24

나는이 decorator을 사용하고 받아 들일 수있는 방법 목록에 "OPTIONS"를 추가하여 Flask로 작업하는 Javascript를 얻었습니다. 데코레이터는 다음과 같이, 경로 데코레이터 아래 사용해야합니다

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

편집 : 링크가 깨진 것 같습니다. 여기 내가 사용한 데코레이터가 있습니다.

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

"NameError : name 'crossdomain'이 정의되지 않았습니다." 문제를 해결하려면 무엇을 가져 옵니까? –

+2

링크에서 데코레이터를 복사하여 플라스크 애플리케이션에 붙여 넣어야합니다. 그곳에 들어가면 크로스 도메인이 정의되고 모든 것이 작동합니다. –

+4

Python 3.x 사용자를위한 중요 사항 : 게시물에 링크 된 데코레이터 코드는 Python 3.x에서 작동하지 않습니다. Python 3.x에서는 basestring을 사용할 수 없기 때문에 "NameError : name 'basestring'is not defined"오류가 발생합니다. "basestring"대신 "list"를 사용하여 코드를 변경하면 작동합니다. – Zafer

0

액세스 제어 허용 허용은 사용자가 아닌 서버에서 보내야합니다. 다른 도메인을 호출하면 브라우저는이 헤더가 서버에 의해 반환되는지 여부를 확인합니다. 그렇지 않으면 호출이 실패합니다. 나는 파이썬을 모른다. 따라서 서버가이 헤더를 보내는 방법을 모르거나 서버를 전혀 수정할 수 없다.

6

실제로 Access-Control-Allow-Origin 헤더 서버 쪽을 수정 플라스크 사이트에서 화려한 조각이있다. http://flask.pocoo.org/snippets/56/

모든 * 도메인이 사용자의 URL에 액세스하거나 헤더 내부에서 선택한 URL을 지정할 수있는 쉬운 방법이 있습니다. MDN's article on CORS에서

: 나는 플라스크-고르 확장자를 사용했다

In this case, the server responds with a Access-Control-Allow-Origin: * which means that the resource can be accessed by any domain in a cross-site manner. If the resource owners at http://bar.other wished to restrict access to the resource to be only from http://foo.example , they would send back: Access-Control-Allow-Origin: http://foo.example .

38

.

는 그 다음이 모든 도메인

나는 재커리의 솔루션을 사용하고 있습니다
+4

업데이트 : 'flask.ext.cors'는 사용되지 않습니다. 대신에 'flask_cors'를 사용하십시오! –

+1

이것은 플라스크에 가장 적합한 솔루션입니다. – VSG24

+0

이로 인해 보안 문제가 발생합니까? – Pitto

2

을 수

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

단지의 pip install flask-cors

를 사용하여 설치합니다. 잘 작동합니다.새로운 장식 배치 할 궁금해하는 사람들을 위해

:

그냥 재커리는 제공된 링크에서 코드를 복사하고 폴더에 .py 파일에

장소를 배치를 어디 파이썬 모듈 (사용하는 시스템 및 가상 환경을 사용하는지 여부에 따라 다름).

플라스크 앱에서 새로 만든 파이썬 모듈에서 crossdomain 메소드를 가져 와서 사용하십시오.

21

이전 질문이긴하지만이 문제가있는 미래의 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() 
+3

나를 위해 완벽하게 일했습니다. 감사합니다! – eddiewould

+0

매우 잘 작업했습니다. 그러나 나는 이것이 장식자를 사용할 때 몇 가지 대신 앱의 모든 끝점에 대한 액세스를 제공합니다. – prasunnair

+0

이 완벽합니다. 이 솔루션은 매우 간단합니다. – xuanhai266

6

pip install flask-cors 는 다음을 추가 명령을 사용하여 플라스크-고르를 설치, 앞서 을 python3에서 실행 또는 때 파이썬 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() 

를 사용하여 :

,
from flask_cors import CORS 
app = Flask(__name__) 
CORS(app) 
관련 문제