如何使用http协议实现社交帐户身份验证

时间:2019-07-11 14:03:36

标签: python google-app-engine flask oauth flask-dance

我正在尝试使用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在某个地方会变得混乱,主要是由于代理。但是这个答案并没有告诉我们如何解决错误。

谢谢您的回答。

2 个答案:

答案 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'
#...