You need to enable JavaScript to run this app. FastAPI部署在VPS的Docker容器中响应无法写入Cookie导致登录失败如何修复?
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI部署在VPS的Docker容器中响应无法写入Cookie导致登录失败如何修复?

无法登录问题排查与解决

问题描述

本地Docker运行容器时可以正常登录,Docker无任何报错,但部署到远程服务器后就无法登录,响应中无法写入Cookie,无错误提示,只会重定向到预设的页面,之后触发报错,原因是Cookie中缺少对应的授权密钥。

相关代码

SignIn接口实现代码

@auth_router.post('/signin')
async def sign_in(response: Response, username: str = Form(...), password: str = Form(...), recaptchav3: str = Form(...)) -> dict:

    is_human = await verify_recaptcha(recaptchav3)
    if is_human['success']:
        user = await authenticate_user(username, password)

        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail='Invalid username or password',
            )

        user_obj = await User_Pydantic.from_tortoise_orm(user)
        user_token = await generate_token(user_obj)

        response.set_cookie(key="Authorization", value=user_token, httponly=True, secure=True, expires=(8*60*60))
        response.headers["Authorization"] = user_token

        user.jwt_token = user_token
        await user.save()

        return {
            'access_token': user_token,
            'token_type': 'bearer'
        }
    else:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail='Invalid captcha',
        )

表单提交JS代码

const request = (method, url, data = null, redirectPage) => {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open(method, url, true)
        // xhr.setRequestHeader('Content-Type', 'multipart/form-data')
        xhr.onerror = function (event) {
            alert(event)
            console.log(event);
        };
        xhr.onload = () => {
        if (xhr.status === 200) {
            return window.location.href = redirectPage;
            return resolve(JSON.parse(xhr.responseText || '{}'))
            } else {
                alert(`Request failed with status ${xhr.status}`)
                reject(new Error(`Request failed with status ${xhr.status}`))
                
                return window.location.reload();
            }
        } 

        if (data) {
            if (typeof data === 'string' || data instanceof String || typeof data.constructor == Object){
                xhr.send(JSON.stringify(data))
            } else {
                xhr.send(data)
            }
        } else {
            xhr.send()
        }
    })
}

signInForm = getElementById('signinform');
handleEvent(signInForm, 'submit', e => {
    e.preventDefault();
    if(!isEmpty(signInForm)){
        signInUsername = getElement('input[name="username"]', signInForm).value;
        signInPassword = getElement('input[name="password"]', signInForm).value;
        recaptchaV3 = getElement('[name="g-recaptcha-response"]').value;
        if(recaptchaV3){
            signInData = new FormData();
            signInData.append('username', signInUsername);
            signInData.append('password', signInPassword);
            signInData.append('recaptchav3', recaptchaV3);
            isLogened = request('POST', '/signin', signInData, 'dashboard');
        } else{
            alert('Перезагрузите страницу');
        }
    }
})

根因与修复方案

核心问题原因

  1. 后端设置Cookie时开启了secure=True属性,该属性要求Cookie只能在HTTPS协议下被浏览器存储,localhost属于浏览器默认的安全上下文,所以本地HTTP访问也能正常写入,但远程服务器如果用HTTP访问,浏览器会直接忽略该Cookie。
  2. XMLHttpRequest默认不带凭据,若前后端跨域部署,就算后端返回Set-Cookie头,浏览器也不会执行写入操作。
  3. 若后端配置了CORS规则,使用*作为允许的源时,带凭据的请求会被浏览器直接拦截,无法正常处理Cookie。

修复步骤

  • 检查远程服务器访问协议:如果使用HTTP访问,将后端set_cookie中的secure=True改为secure=False,或者给远程服务器配置HTTPS证书,用HTTPS协议访问。
  • 在JS的XHR初始化逻辑中,xhr.open之后添加xhr.withCredentials = true,允许请求携带凭据,同时接收响应的Cookie写入。
  • 若前后端跨域部署,后端CORS配置需要设置allow_credentials=True,并且指定具体的允许访问源,不能使用*通配符。
  • 可选优化:调整XHR的onload逻辑顺序,先处理响应再执行跳转,避免后续逻辑无法执行:
xhr.onload = () => {
    if (xhr.status === 200) {
        resolve(JSON.parse(xhr.responseText || '{}'))
        window.location.href = redirectPage;
    } else {
        alert(`Request failed with status ${xhr.status}`)
        reject(new Error(`Request failed with status ${xhr.status}`))
        window.location.reload();
    }
}

内容的提问来源于stack exchange,提问作者WhyIsThatHappening

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 03:27:03