【问题标题】:How to implement social account authentication using http protocol如何使用http协议实现社交账号认证
【发布时间】:2019-07-25 22:59:51
【问题描述】:

我正在尝试使用 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 时,服务器将我重定向到选择谷歌帐户页面。然后,当我选择一个帐户时,我收到此错误:

INFO 2019-07-11 14:47:13,476 module.py:861] 默认值:“GET /login/google HTTP/1.1" 302 989 警告 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,得到 . Traceback(最近一次调用 最后):文件 "C:\Users\tah\Documents\some-name\m\src\lib\urllib3\connectionpool.py", 第 399 行,在 _make_request 中 assert_header_parsing(httplib_response.msg) 文件“C:\Users\Tah\Documents\some-name\m\src\lib\urllib3\util\response.py”, 第 56 行,在 assert_header_parsing 中 类型(标题)))类型错误:预期的httplib.Message,得到。错误消息:EXCEPTION IN (1982, ('连接中断: IncompleteRead(35 bytes read)', IncompleteRead(35 bytes read))) ('连接中断: IncompleteRead(35 bytes read)', IncompleteRead(35 字节读取)) INFO 2019-07-11 13:47:21,884recording.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] 默认值:“获取 /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=consent HTTP/1.1" 500 41241

来自this answer,我了解到如果 Flask-Dance 使用 HTTP 生成重定向 URL,这意味着 Flask 认为传入的请求使用的是 HTTP。如果传入的请求实际上使用的是 HTTPS,那么 Flask 就会在某个地方感到困惑,主要是因为代理。但是这个答案并没有告诉我们如何解决这个错误。

感谢您的回答。

【问题讨论】:

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


    【解决方案1】:

    我假设你已经在 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'
    #...
    

    【讨论】:

      【解决方案2】:

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-07
        • 2016-08-09
        • 1970-01-01
        • 1970-01-01
        • 2015-11-07
        • 2016-07-29
        • 1970-01-01
        相关资源
        最近更新 更多