mismatching_state:CSRF 警告! fastapi中请求和响应的状态不相等

Posted

技术标签:

【中文标题】mismatching_state:CSRF 警告! fastapi中请求和响应的状态不相等【英文标题】:mismatching_state: CSRF Warning! State not equal in request and response in fastapi 【发布时间】:2021-11-14 20:42:08 【问题描述】:

我正在尝试将 gitlab 集成到我的 fastapi 项目中,但是,这个问题让我很生气。我正在使用 authlib。 gitlab 集成的过程是当用户点击连接按钮时,会弹出 gitlab 授权窗口,当点击授权按钮时,它会运行 redirect_url,这是我的 api url(http://localhost:8888/auth/gitlab?code=asdkjfasdjfkasdjkfasjdkjlsadajk&state=_gitlab)。这是代码

if settings.BACKEND_CORS_ORIGINS:
    app.add_middleware(SessionMiddleware, secret_key=settings.SECRET_KEY)
    app.add_middleware(
        CORSMiddleware,
        allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

config = Config(".env")
oauth = OAuth(config)
oauth.register(
    name="gitlab",
    client_id=settings.GITLAB_CLIENT_ID,
    client_secret=settings.GITLAB_CLIENT_SECRET,
    authorize_url="https://gitlab.com/oauth/authorize",
    client_kwargs="scope": "read_user+profile",
)

@app.get("/auth/gitlab")
async def auth_gitlab(request: Request):
    print("###################")
    print("request", request, request.session)
    # '_gitlab_authlib_redirect_uri_': 'http://localhost:8888/auth/gitlab'
    gitlab = oauth.create_client("gitlab")
    try:
        token = await gitlab.authorize_access_token(request)
        print("token", token)
        user = await gitlab.parse_id_token(request, token)
        print("user", dict(user))
        return "token": token
    except OAuthError as error:
        print("oauth error", error, error.error)

我的弹出窗口的 oauth url 是

const oauthUrl = `$GITLAB_URL/oauth/authorize?client_id=$client_id&response_type=code&scope=$scope&state=$
          state + '_gitlab'
        &redirect_uri=$redirect_uri&allow_signup=$allow_signup`

我同时使用了 0.15.4 和 1.0.0a2 版本的 Authlib,但仍然遇到同样的问题。

更新: 我的 /auth/gitlab 的 request.session 看起来像

'_state_gitlab_WiBjFgSNd5BV1A7hlDHX0': 'data': 'redirect_uri': 'http://localhost:8888/auth/gitlab', 'url': 'https://gitlab.com/oauth/authorize?response_type=code&client_id=e2dc9edc72dbcf5524910eca1d0577473b6005a833c97&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fauth%2Fgitlab&scope=read_user%2Bprofile&state=WiBjFgSNd5BV1A7hlDHX0', 'exp': 1632275167.3455658, '_state_gitlab_3YUfQJ4ubbNjErkqY4dJ7ZQMzzmCqt': 'data': 'redirect_uri': 'http://localhost:8888/auth/gitlab', 'url': 'https://gitlab.com/oauth/authorize?response_type=code&client_id=e2dc9edc72dbcf5524910eca1d0577473b6005a833c97&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fauth%2Fgitlab&scope=read_user%2Bprofile&state=3YUfQJ4ubbNjErkqY4dJ7ZQMzzmCqt', 'exp': 1632275280.9188702, '_state_gitlab_S3OQ93EDvralFGYiu5HxRWxUMWZFQh': 'data': 'redirect_uri': 'http://localhost:8888/auth/gitlab', 'url': 'https://gitlab.com/oauth/authorize?response_type=code&client_id=e2dc9edc72dbcf5524910eca1d0577473b6005a833c97&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fauth%2Fgitlab&scope=read_user%2Bprofile&state=S3OQ93EDvralFGYiu5HxRWxUMWZFQh', 'exp': 1632275404.760191, '_state_gitlab_vImiUiWK4VIUL82PywWlIZ1K9yA5Ss': 'data': 'redirect_uri': 'http://localhost:8888/auth/gitlab', 'url': 'https://gitlab.com/oauth/authorize?response_type=code&client_id=e2dc9edc72dbcf5524910eca1d0577473b6005a833c97&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fauth%2Fgitlab&scope=read_user%2Bprofile&state=vImiUiWK4VIUL82PywWlIZ1K9yA5Ss', 'exp': 1632275509.933466

当我将 oauth_url 更改为弹出窗口时

const oauthUrl = `$GITLAB_URL/oauth/authorize?client_id=$client_id&response_type=code&scope=$scope&state=$
          state + 'WiBjFgSNd5BV1A7hlDHX0'
        &redirect_uri=$redirect_uri&allow_signup=$allow_signup`

我得到 python TypeError: Invalid type for url. Expected str or httpx.URL, got <class 'NoneType'>: None

【问题讨论】:

【参考方案1】:

对我来说,问题是 SessionMiddleware 选项上的 https_only 参数。 只有当我将其设置为 True 时它才有效。

【讨论】:

以上是关于mismatching_state:CSRF 警告! fastapi中请求和响应的状态不相等的主要内容,如果未能解决你的问题,请参考以下文章

警告:无法验证 CSRF 令牌的真实性

“警告:无法验证 CSRF 令牌真实性”错误 - 带有 Devise 和 :token_authenticable 的 CORS

基本 .ajax 发布到 rails 3.2.2 脚手架,生成“警告:无法验证 CSRF 令牌真实性”

Rails 3.1 - 忽略 CSRF?

CSRF来袭

Laravel 5:没有 CSRF 检查的 POST