交叉源请求被阻止 - 创建实体GAE数据存储 [英] Cross Origin Request Blocked - Create entity GAE datastore

查看:324
本文介绍了交叉源请求被阻止 - 创建实体GAE数据存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注此Google Firebase教程: https ://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine

I am following this Google Firebase Tutorial: https://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine

我在最后一部分它将注释添加到数据存储中,但是当我按下按钮添加注释时,它不会执行任何操作,并在Firefox Web控制台中给出以下错误消息:

I'm at the last part where it adds the note to the datastore but when I press the button to add the note it doesn't do anything and gives me the following error in Firefox web console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://backend-dot-i7643225firenotes.appspot.com/notes. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

任何想法是什么引起的?我没有触及Google提供的代码,但无论如何我都会加入它。其余部分可以在这里找到:

Any ideas what causes this? I haven't touched the code Google provided but I'll include it anyway. The rest of it can be found here:

https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/standard/firebase/firenotes

main.js

// Copyright 2016, Google, Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

$(function(){
  // This is the host for the backend.
  // TODO: When running Firenotes locally, set to http://localhost:8081. Before
  // deploying the application to a live production environment, change to
  // https://backend-dot-<PROJECT_ID>.appspot.com as specified in the
  // backend's app.yaml file.
  var backendHostUrl = 'https://backend-dot-i7643225firenotes.appspot.com'; //localhost:8081

  // Initialize Firebase
  // TODO: Replace with your project's customized code snippet
  var config = {
    apiKey: "REMOVED",
    authDomain: "REMOVED",
    databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
    storageBucket: "<BUCKET>.appspot.com",
  };

  // This is passed into the backend to authenticate the user.
  var userIdToken = null;

  // Firebase log-in
  function configureFirebaseLogin() {

    firebase.initializeApp(config);

    // [START onAuthStateChanged]
    firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        $('#logged-out').hide();
        var name = user.displayName;

        /* If the provider gives a display name, use the name for the
        personal welcome message. Otherwise, use the user's email. */
        var welcomeName = name ? name : user.email;

        user.getToken().then(function(idToken) {
          userIdToken = idToken;

          /* Now that the user is authenicated, fetch the notes. */
          fetchNotes();

          $('#user').text(welcomeName);
          $('#logged-in').show();

        });

      } else {
        $('#logged-in').hide();
        $('#logged-out').show();

      }
    // [END onAuthStateChanged]

    });

  }

  // [START configureFirebaseLoginWidget]
  // Firebase log-in widget
  function configureFirebaseLoginWidget() {
    var uiConfig = {
      'signInSuccessUrl': '/',
      'signInOptions': [
        // Leave the lines as is for the providers you want to offer your users.
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,

        //firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        //firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        //firebase.auth.GithubAuthProvider.PROVIDER_ID,

        firebase.auth.EmailAuthProvider.PROVIDER_ID
      ],
      // Terms of service url
      'tosUrl': '<your-tos-url>',
    };

    var ui = new firebaseui.auth.AuthUI(firebase.auth());
    ui.start('#firebaseui-auth-container', uiConfig);
  }
  // [END configureFirebaseLoginWidget]

  // [START fetchNotes]
  // Fetch notes from the backend.
  function fetchNotes() {
    $.ajax(backendHostUrl + '/notes', {
      /* Set header for the XMLHttpRequest to get data from the web server
      associated with userIdToken */
      headers: {
        'Authorization': 'Bearer ' + userIdToken
      }
    }).then(function(data){
      $('#notes-container').empty();
      // Iterate over user data to display user's notes from database.
      data.forEach(function(note){
        $('#notes-container').append($('<p>').text(note.message));
      });
    });
  }
  // [END fetchNotes]

  // [START signOutBtn]
  // Sign out a user
  var signOutBtn =$('#sign-out');
  signOutBtn.click(function(event) {
    event.preventDefault();

    //FirebaseAuth.getInstance().signOut();
    firebase.auth().signOut().then(function() {
      console.log("Sign out successful");
    }, function(error) {
      console.log(error);
    });
  });
  // [END signOutBtn]

  // [START saveNoteBtn]
  // Save a note to the backend
  var saveNoteBtn = $('#add-note');
  saveNoteBtn.click(function(event) {
    event.preventDefault();

    var noteField = $('#note-content');
    var note = noteField.val();
    noteField.val("");

    /* Send note data to backend, storing in database with existing data
    associated with userIdToken */
    $.ajax(backendHostUrl + '/notes', {
      headers: {
        'Authorization': 'Bearer ' + userIdToken
      },
      method: 'POST',
      data: JSON.stringify({'message': note}),
      contentType : 'application/json'
    }).then(function(){
      // Refresh notebook display.
      fetchNotes();
    });

  });
  // [END saveNoteBtn]

  configureFirebaseLogin();
  configureFirebaseLoginWidget();

});

main.py

main.py

# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# [START app]
import logging

from flask import Flask, jsonify, request
import flask_cors
from google.appengine.ext import ndb
import google.auth.transport.requests
import google.oauth2.id_token
import requests_toolbelt.adapters.appengine

# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()
HTTP_REQUEST = google.auth.transport.requests.Request()

app = Flask(__name__)
flask_cors.CORS(app)


# [START note]
class Note(ndb.Model):
    """NDB model class for a user's note.

    Key is user id from decrypted token.
    """
    friendly_id = ndb.StringProperty()
    message = ndb.TextProperty()
    created = ndb.DateTimeProperty(auto_now_add=True)
# [END note]


# [START query_database]
def query_database(user_id):
    """Fetches all notes associated with user_id.

    Notes are ordered them by date created, with most recent note added
    first.
    """
    ancestor_key = ndb.Key(Note, user_id)
    query = Note.query(ancestor=ancestor_key).order(-Note.created)
    notes = query.fetch()

    note_messages = []

    for note in notes:
        note_messages.append({
            'friendly_id': note.friendly_id,
            'message': note.message,
            'created': note.created
        })

    return note_messages
# [END query_database]


# [START list_notes]
@app.route('/notes', methods=['GET'])
def list_notes():
    """Returns a list of notes added by the current Firebase user."""

    # Verify Firebase auth.
    # [START verify_token]
    id_token = request.headers['Authorization'].split(' ').pop()
    claims = google.oauth2.id_token.verify_firebase_token(
        id_token, HTTP_REQUEST)
    if not claims:
        return 'Unauthorized', 401
    # [END verify_token]

    notes = query_database(claims['sub'])

    return jsonify(notes)
# [END list_notes]


# [START add_note]
@app.route('/notes', methods=['POST', 'PUT'])
def add_note():
    """
    Adds a note to the user's notebook. The request should be in this format:

        {
            "message": "note message."
        }
    """

    # Verify Firebase auth.
    id_token = request.headers['Authorization'].split(' ').pop()
    claims = google.oauth2.id_token.verify_firebase_token(
        id_token, HTTP_REQUEST)
    if not claims:
        return 'Unauthorized', 401

    # [START create_entity]


    data = request.get_json()

    # Populates note properties according to the model,
    # with the user ID as the key name.
    note = Note(
        parent=ndb.Key(Note, claims['sub']),
        message=data['message'])

    # Some providers do not provide one of these so either can be used.
    note.friendly_id = claims.get('name', claims.get('email', 'Unknown'))
    # [END create_entity]

    # Stores note in database.
    note.put()

    return 'OK', 200
# [END add_note]


@app.errorhandler(500)
def server_error(e):
    # Log the error and stacktrace.
    logging.exception('An error occurred during a request.')
    return 'An internal error occurred.', 500
# [END app]


推荐答案

我试过本教程本人,并且一切正常,对我来说,所以我想你可能会跳过一些步骤,或者你有一些错误的配置。

I have tried the tutorial myself, and everything worked fine for me, so I guess you might have either skipped some step or you have some wrong configuration.

我的例子和我之间唯一显着的差异是以下内容,所以您可以尝试修改它们以查看问题是否得到解决:

The only notable differences I see between your example and mine, are the following, so you can try modifying them in order to see if your issue gets solved:


  • 我在代码中看到了一些 import error ,所以我添加了这一行 werkzeug == 0.12.2 backend / requirements.txt 文件,其中包括将要安装的库。最新版本的 werzeug 库已经将一些依赖项移动到了嵌套文件夹中,这是为什么一些导入失败的原因(您可以阅读更多这里)。然后,删除 lib 文件夹并重新运行命令以安装库 pip install -r requirements.txt -t lib 。在进行此修改之前,我遇到了与您的问题相同的问题,在我的应用程序中单击 Save 按钮时没有发生任何事情,但在更改后,它工作正常。

  • 我的 frontend / main.js 文件中的 config 变量有一些您已删除的其他字段。我获取了本指南后的参数并转到我的Firebase控制台,点击向您的网络应用添加Firebase 按钮,然后复制以下内容:
  • I saw some import error in my code, so I added this line werkzeug==0.12.2 to the backend/requirements.txt file, which includes the libraries that will be installed. The latest releases of the werzeug library have moved some dependencies to nested folders, reason why some imports were failing (you can read more here). Then, remove the lib folder and rerun the command to install the libraries pip install -r requirements.txt -t lib. Before doing this modification, I had the same problem as yours, nothing happened when clicking on the Save button in my application, but after the change, it worked fine.
  • The config variable in my frontend/main.js file has some additional field which you have removed. I got the parameters following this guide and going to my Firebase console, clicking in the round Add Firebase to your web app button, and copying the content as follows:

config 前端/ main.js 中的变量:

config variable in frontend/main.js:

var config = {
    apiKey: "<API_KEY>",
    authDomain: "<PROJECT_ID>.firebaseapp.com",
    databaseURL: "https://<PROJECT_ID>.firebaseio.com",
    projectId: "<PROJECT_ID>",
    storageBucket: "<PROJECT_ID>.appspot.com",
    messagingSenderId: "<SOME_ID>"
  };

至于其他方面,对我来说一切都很正常,只是我试过用 firebase.auth.GoogleAuthProvider.PROVIDER_ID ,我已经删除了所有其他内容。我也在运行生产中的应用程序(App Engine标准版),而不是使用本地的开发服务器。我也看了一下我的CORS配置,我没有什么特别的,只有你已经在你的代码中有几行:

As for the rest, everything looks fine to me, only that I have just tried using firebase.auth.GoogleAuthProvider.PROVIDER_ID and I have removed all the rest. I am also running the application in production (App Engine Standard), not using the local Development Server. I had a look at my CORS configuration too, and I have nothing special, only the couple of lines you already have in your code:

app = Flask(__name__)
flask_cors.CORS(app)

您应该尝试并提供了我提供的几条建议,并随时提供有关该错误的更多信息。

You should try with the couple of suggestions I provided, and come back with more information about the error if it keeps coming up.

这篇关于交叉源请求被阻止 - 创建实体GAE数据存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆