为什么FastAPI不把Cookie返回给我的前端,这是一款Reaction应用程序?
以下是我的代码:
@router.post("/login")
def user_login(response: Response,username :str = Form(),password :str = Form(),db: Session = Depends(get_db)):
user = db.query(models.User).filter(models.User.mobile_number==username).first()
if not user:
raise HTTPException(400, detail='wrong phone number or password')
if not verify_password(password, user.password):
raise HTTPException(400, detail='wrong phone number or password')
access_token = create_access_token(data={"sub": user.mobile_number})
response.set_cookie(key="fakesession", value="fake-cookie-session-value") #here I am set cookie
return {"status":"success"}
当我从Swagger UI Autodocs登录时,我可以在Chrome浏览器上使用DevTool在响应头中看到Cookie。然而,当我从我的Reaction应用程序登录时,没有返回任何cookie。我使用AXIOS发送如下请求:await axios.post(login_url, formdata)
1条答案
按热度按时间d8tt03nd1#
首先,确保在执行Axios POST请求时没有返回错误,并且您得到了带有
200
状态代码的"status": "success"
响应。其次,正如您提到的那样,您在前端使用Reaction-需要侦听与FastAPI后端使用的端口不同的端口,这意味着您正在执行CORS请求-您需要将
withCredentials
属性设置为true
(缺省情况下设置为false
),以便允许从/向其他来源接收/发送凭据,例如cookies和HTTP authentication头。两台服务器具有相同的域和协议,但不同端口,例如http://localhost:8000
和http://localhost:3000
,被视为不同的来源(请参阅FastAPI documentation on CORS和this answer,其中介绍了一般的Cookie,以及设置跨域Cookie的解决方案-在您的情况下,实际上并不需要跨域Cookie,因为后端和前端的域是相同的,因此,正常设置Cookie会很好)。请注意如果您是从浏览器访问您在
http://localhost:3000
上的React前端,那么您对FastAPI后端的Axios请求应该使用URL中的localhost
域,例如axios.post('http://localhost:8000',...
,不是http://127.0.0.1:8000
,因为localhost
和127.0.0.1
是两个不同的域,因此,否则将无法为localhost
域创建cookie,因为它将为127.0.0.1
创建,即axios
请求中使用的域(这将是跨域cookie的情况,如上面链接的答案所述)。因此,要接受服务器发送的Cookie,您需要在Axios请求中使用
withCredentials: true
;否则,这些Cookie将在响应中被忽略(当withCredentials
设置为false
时,这是默认行为;因此,防止不同的域为其自己的域设置Cookie)。如果您希望将Cookie发送到服务器,以便可以对用户进行身份验证并提供对受保护路由的访问,则必须在对您的API的每个后续请求中包括相同的withCredentials: true
属性。因此,包含凭据的Axios请求应如下所示:
fetch()
请求(即使用Fetch API)中的等价物是credentials: 'include'
。credentials
的默认值为same-origin
。使用credentials: 'include'
将导致浏览器在同源和跨域请求中都包含凭据,并设置在跨域响应中发回的任何cookie。例如:注意事项
要使上述两种方法之一发挥作用,您需要显式指定允许的来源,如this answer中所述(即在幕后设置
Access-Control-Allow-Origin
响应头)。例如:使用
"*"
通配符将只允许某些类型的通信,排除涉及credentials
的所有内容,如cookie、授权头部等。此外,在使用
CORSMiddleware
(将Access-Control-Allow-Credentials
响应头设置为true
)时,请确保设置allow_credentials=True
。