我正在尝试使用Flask,Google App Engine和Flask-dance在本地实施Google社交登录。
我遵循了link中Flask-dance作者提供的示例。
这是主文件:
from flask import Flask, url_for, redirect
from flask_dance.contrib.google import make_google_blueprint, google
from flask_dance.consumer import oauth_authorized, oauth_error
from werkzeug.contrib.fixers import ProxyFix
app = Flask('application')
app.wsgi_app = ProxyFix(app.wsgi_app)
# You must configure these 3 values from Google APIs console
# https://code.google.com/apis/console
GOOGLE_CLIENT_ID = 'my-client-id'
GOOGLE_CLIENT_SECRET = 'my-client-secret'
app.config["GOOGLE_OAUTH_CLIENT_ID"] = GOOGLE_CLIENT_ID
app.config["GOOGLE_OAUTH_CLIENT_SECRET"] = GOOGLE_CLIENT_SECRET
google_bp = make_google_blueprint(
client_id=app.config['GOOGLE_OAUTH_CLIENT_ID'],
client_secret=app.config['GOOGLE_OAUTH_CLIENT_SECRET'],
redirect_to="index_man_2",
scope=["https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email"]
)
app.register_blueprint(google_bp, url_prefix="/login")
@app.route("/login-gmail")
def index_gmail():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.get("/oauth2/v1/userinfo")
assert resp.ok, resp.text
return "ok"
当我访问http://localhost:8080/login-gmail时,服务器会将我重定向到Google帐户页面。然后,当我选择一个帐户时,出现此错误:
INFO 2019-07-11 14:47:13,476 module.py:861]默认:“获取 / login / google HTTP / 1.1“ 302989警告2019-07-11 14:47:21,345 urlfetch_stub.py:575]从URLFetch删除了禁止的标头 要求:['Content-Length']警告2019-07-11 13:47:21,828 connectionpool.py:403]无法解析头 (url = https://accounts.google.com:443/o/oauth2/token):预期 httplib.Message,得到了。追溯(最近通话 最后):文件 “ C:\ Users \ tah \ Documents \ some-name \ m \ src \ lib \ urllib3 \ connectionpool.py”, _make_request中的第399行 assert_header_parsing(httplib_response.msg)文件“ C:\ Users \ Tah \ Documents \ some-name \ m \ src \ lib \ urllib3 \ util \ response.py”, 第56行,在assert_header_parsing中 type(headers)))TypeError:预期的httplib.Message,得到了。错误消息:EXCEPTION IN(1982,('连接断开: IncompleteRead(读取35个字节)',IncompleteRead(读取35个字节))) ('连接断开:IncompleteRead(读取35个字节)',IncompleteRead(35 读取的字节数))INFO 2019-07-11 13:47:21,884 recording.py:676]已保存; 密钥: appstats :041000,部分:455字节,完整:18063字节, 管理费用:0.000 + 0.012;链接: http://localhost:8080/_ah/stats/details?time=1562852841009信息
2019-07-11 14:47:21,895 module.py:861]默认值:“ GET /login/google/authorized?state=sfUHmqfKiy61fnvh1UUsVydJv3vO5L&code=4%2FgwHWN8roL2HIxqxtBoFKySXod_jErJ0NB7ofNpdFtLwS2Zebc2rx959sPDOvUThrdlKfQEKWAj0bEbtJxBsskao&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth %2Fuserinfo.email + openid&authuser = 2&session_state = 7ea8a7963e2773849220b0eb3ddf063f9c5e3ef8..3331&prompt =同意 HTTP / 1.1“ 500 41241
从this answer中,我了解到,如果Flask-Dance正在使用HTTP生成重定向URL,则意味着Flask认为传入的请求正在使用HTTP。如果传入的请求实际上是使用HTTPS,则Flask在某个地方会变得混乱,主要是由于代理。但是这个答案并没有告诉我们如何解决错误。
谢谢您的回答。
答案 0 :(得分:0)
Flask依赖的werkzeug库最近更新到0.15版。 0.15版中有一些向后不兼容的更改,包括对ProxyFix中间件的更改。从发布的代码示例中,您似乎正在以适用于werkzeug 0.14的方式导入和使用它,但您需要对0.15进行一些更改。您应该改用以下方法:
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask('application')
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
答案 1 :(得分:0)
我假设您已经在app.yaml中定义了此环境变量:
env_variables:
OAUTH_INSECURE_TRANSPORT: '1'
OAUTHLIB_INSECURE_TRANSPORT: '1'
要解决您的问题,您需要使用requests toolbelt。该工具带带有几个不同的传输适配器,供您用于请求。
首先,您需要安装该库:
pip install -t lib requests-toolbelt
然后您需要将此行添加到主文件中:
import requests_toolbelt.adapters.appengine
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()
因此,主文件将与此类似:
from flask import Flask, url_for, redirect
from flask_dance.contrib.google import make_google_blueprint, google
from flask_dance.consumer import oauth_authorized, oauth_error
import requests_toolbelt.adapters.appengine
app = Flask('application')
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()
# You must configure these 3 values from Google APIs console
# https://code.google.com/apis/console
GOOGLE_CLIENT_ID = 'my-client-id'
GOOGLE_CLIENT_SECRET = 'my-client-secret'
#...