【问题标题】:MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and responseMismatchingStateError: mismatching_state: CSRF 警告!请求和响应中的状态不相等
【发布时间】:2020-09-07 08:20:37
【问题描述】:

这让我非常抓狂,让我无法进行本地开发/测试。

我有一个使用 authlib 的烧瓶应用程序(仅限客户端功能)。当用户点击我的主页时,我的烧瓶后端会将他们重定向到 /login,然后再重定向到 Google Auth。然后 Google Auth 将它们发布回我的应用程序的 /auth 端点。

几个月来,我一直遇到 authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF 警告的临时问题!请求和响应中的状态不相等。感觉就像是 cookie 问题,大多数时候,我只是打开一个新的浏览器窗口或隐身或尝试清除缓存,最终,它有点工作。

但是,我现在在 docker 容器内运行完全相同的应用程序,并且在某个阶段它可以正常工作。我不知道我做了什么改变,但是每当我浏览到 localhost/ 或 127.0.0.1/ 并通过身份验证过程(每次清除 cookie 以确保我没有自动登录)时,我都会不断被重定向回 l​​ocalhost /auth?state=blah blah blah 我遇到了这个问题: authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF 警告!请求和响应中的状态不相等。

我认为我的代码的相关部分是:

@app.route("/", defaults={"path": ""})
@app.route("/<path:path>")
def catch_all(path: str) -> Union[flask.Response, werkzeug.Response]:
    if flask.session.get("user"):
        return app.send_static_file("index.html")
    return flask.redirect("/login")


@app.route("/auth")
def auth() -> Union[Tuple[str, int], werkzeug.Response]:
    token = oauth.google.authorize_access_token()
    user = oauth.google.parse_id_token(token)
    flask.session["user"] = user
    return flask.redirect("/")


@app.route("/login")
def login() -> werkzeug.Response:
    return oauth.google.authorize_redirect(flask.url_for("auth", _external=True))

我将非常感谢任何帮助。

当我在本地运行时,我开始:

export FLASK_APP=foo && flask run

当我在 docker 容器中运行时,我开始:

.venv/bin/gunicorn -b :8080 --workers 16 foo

【问题讨论】:

  • 啊,重要的额外信息。如果我从 --workers 1 开始,我就没有这个问题。我错过了什么?

标签: python docker flask authlib


【解决方案1】:

问题是 SECRET_KEY 是使用 os.random 填充的,这会为不同的工作人员产生不同的值,因此无法访问会话 cookie。

【讨论】:

  • 在将我的代码从“传统”部署 (flask+uwsgi+nginx) 移动到 docker(gunicorn) 后,我遇到了“CSRF 令牌无效”问题。这是唯一有效的方法。
【解决方案2】:

@adamcunnington 可以在这里调试它:

@app.route("/auth")
def auth() -> Union[Tuple[str, int], werkzeug.Response]:
    # Check these two values
    print(flask.request.args.get('state'), flask.session.get('_google_authlib_state_'))

    token = oauth.google.authorize_access_token()
    user = oauth.google.parse_id_token(token)
    flask.session["user"] = user
    return flask.redirect("/")

检查request.argssession 中的值,看看发生了什么。

也许是因为Flask session not persistent across requests in Flask app with Gunicorn on Heroku

【讨论】:

  • 谢谢。结果如下: - Docker + gunicorn(16 个工人)TrhHO856SVe7EA9INtHKZ85rnieDKS 无 authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF 警告!请求和响应中的状态不相等。 - Docker + gunicorn (1 worker) enq7AxTUI5lfhTvDwvMKRe6pn5Hah8 enq7AxTUI5lfhTvDwvMKRe6pn5Hah8 - Flask webserver eqahv9lpZOHpPmTabsqBNSDtEN4TEI eqahv9lpZOHpPmTabsqBNSDtEN4TEI 为什么 16 个 worker 场景会导致问题?我仍然只提出 1 个请求。
  • @adamcunnington 我正在尝试使用github.com/authlib/demo-oauth-client/tree/master/… gunicorn app:app -w 16 --bind=0.0.0.0:5000 重现该问题,但我无法重现它。什么时候发生?试了很多次,还是没有报错。
  • 它会立即发生——一旦我用 16 个工作人员启动网络服务器,如果我尝试访问主页——它会将我重定向到登录,我总是会收到不匹配的 CSRF 错误。
  • @adamcunnington 关注 authlib 推特账号,我们可以安排一次 Zoom 会议来调试这个问题。我给你发私信。
  • @adamcunnington 你能创建一个示例 github repo 来重现这个问题吗?可能是因为这个stackoverflow.com/questions/30984622/…
猜你喜欢
  • 1970-01-01
  • 2020-12-04
  • 2021-11-14
  • 2021-12-06
  • 2018-11-29
  • 1970-01-01
  • 2012-03-01
  • 2015-05-28
  • 2017-10-31
相关资源
最近更新 更多