Docker部署FastAPI与Streamlit的Cookie/Token获取异常问题
问题
在Docker容器中运行FastAPI应用,尝试从请求中获取token,但无法获取对应的Cookies/Token。相关代码如下:
FastAPI获取Cookie接口代码
@user.get('/get_cookies') async def get_cookies(request: Request, user: user_dependency): if not user: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED) access_token = request.cookies.get('access_token') refresh_token = request.cookies.get('refresh_token') print(f"Access Token: {access_token}, Refresh Token: {refresh_token}") if access_token and refresh_token: return {'access_token': access_token, 'refresh_token': refresh_token} else: return "Failed to fetch access token and refresh token"
Streamlit应用调用API的代码
import streamlit as st import requests p_uri = "http://localhost:8000/user/get_cookies" response = requests.get(p_uri) st.write(response.json())
HTTP Cookie设置代码
response = RedirectResponse(url='http://localhost:8501') response.set_cookie( key='jwt_token', value=jwt_token, httponly=False, max_age=60 * 60 * 24 * 30, secure=False, samesite='lax', domain='localhost', path='/' ) response.set_cookie( key='access_token', value=token, max_age=60 * 60 * 24 * 30, httponly=False, secure=False, samesite='lax', domain='localhost', path='/' ) response.set_cookie( key='refresh_token', value=refresh_token, max_age=60 * 60 * 24 * 30, httponly=False, secure=False, samesite='lax', domain='localhost', path='/' ) return response
解决方案
1. 修正Docker网络与Cookie域名匹配
FastAPI运行在Docker容器内时,localhost指向容器自身而非宿主机。需调整两处配置:
- 将Streamlit请求地址改为宿主机IP或Docker映射后的宿主机地址(如
http://192.168.1.100:8000/user/get_cookies); - 避免硬编码
localhost为Cookie的domain,通过FastAPI的Request对象动态获取请求主机:
from fastapi import Request async def set_auth_cookies(request: Request): host = request.headers.get('host', '').split(':')[0] response = RedirectResponse(url=f'http://{host}:8501') response.set_cookie( key='access_token', value=token, max_age=60*60*24*30, httponly=False, secure=False, samesite='lax', domain=host, path='/' ) # 其他Cookie设置同理 return response
2. 让Streamlit请求携带Cookie
requests.get默认不会自动携带浏览器中的Cookie,需手动处理:
- 从Streamlit会话中获取Cookie并传入请求:
import streamlit as st import requests # 获取浏览器请求中的Cookie cookies = st.experimental_get_query_params().get('cookies', {}) # 或从session_state读取已存储的Cookie # cookies = st.session_state.get('auth_cookies', {}) p_uri = "http://192.168.1.100:8000/user/get_cookies" response = requests.get(p_uri, cookies=cookies) st.write(response.json())
- 或通过前端JS发起请求自动携带Cookie:
import streamlit as st st.components.v1.html(""" <script> fetch('http://192.168.1.100:8000/user/get_cookies', { credentials: 'include' }) .then(res => res.json()) .then(data => window.parent.postMessage(data, '*')); </script> """, height=0) def handle_message(msg): st.write(msg.data) st.experimental_set_query_params() st.experimental_connection("postMessage", on_message=handle_message)
3. 确认Docker端口映射正确
启动FastAPI容器时必须映射端口到宿主机,确保外部能访问:
docker run -p 8000:8000 your-fastapi-image-name
4. 检查SameSite与Secure参数
由于FastAPI(8000端口)和Streamlit(8501端口)属于同一域名下的不同端口,SameSite='lax'是合规的,但需确保secure参数设为False(非HTTPS环境),避免Cookie被浏览器拦截。
内容的提问来源于stack exchange,提问作者Imisioluwa
相关产品推荐
相关产品推荐

