jab*_*934 5 javascript python reactjs axios fastapi
为什么 FastAPI 不将 cookie 返回到我的前端(这是一个 React 应用程序)?
这是我的代码:
@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"}
Run Code Online (Sandbox Code Playgroud)
当我从 Swagger UI autodocs 登录时,我可以使用 Chrome 浏览器上的 DevTools 在响应标头中看到 cookie。但是,当我从 React 应用程序登录时,没有返回 cookie。我正在使用 axios 发送这样的请求:
await axios.post(login_url, formdata)
Chr*_*ris 12
首先,创建 cookie,如下例所示,并确保执行 Axios POST 请求时没有返回错误,并且您收到\'status\': \'success\'带有200状态代码的响应。您可能想看看这个答案,它也解释了如何使用max_age和expires标志。
from fastapi import FastAPI, Response\n\napp = FastAPI()\n\n@app.get(\'/\')\ndef main(response: Response):\n response.set_cookie(key=\'token\', value=\'some-token-value\', httponly=True) \n return {\'status\': \'success\'}\nRun Code Online (Sandbox Code Playgroud)\n其次,正如您提到的,您在前端\xe2\x80\x94中使用React,它需要侦听与FastAPI后端使用的端口不同的端口,这意味着您正在执行CORS请求\xe2\x80\x94您需要将该withCredentials属性设置为true(默认情况下设置为false),以允许从其他来源接收/发送凭据,例如cookie和HTTP 身份验证标头。两台服务器具有相同的域和协议,但端口不同,例如,http://localhost:8000被http://localhost:3000认为是不同的来源(请参阅CORS 上的 FastAPI 文档和此答案,它提供了有关 cookie 的一般详细信息,以及设置跨域 cookie\xe2\ 的解决方案x80\x94 在你的情况下实际上并不需要,因为后端和前端的域是相同的,因此,照常设置 cookie 就可以了。
请注意http://localhost:3000,如果您通过在浏览器地址栏中输入来访问 React 前端,那么您对 FastAPI 后端的 Axios 请求应使用localhostURL 中的域,例如axios.post(\'http://localhost:8000\',...和not axios.post(\'http://127.0.0.1:8000\',...,因为localhost和127.0.0.1是两个不同的域,因此,否则,该 cookie 将无法为该域创建localhost,因为它将为127.0.0.1,即在 中使用的域创建axios创建的(然后,这将是跨域 cookie 的情况,如上面链接的答案中所述,对于您的情况,这也是不需要的)。
因此,要接受服务器发送的cookie,您需要withCredentials: true在axios请求中使用;withCredentials否则,响应中的 cookie 将被忽略(当设置为时,这是默认行为false;因此,可以防止不同的域为自己的域设置 cookie)。相同withCredentials: true如果您希望将 cookie 发送到服务器,则必须在对 API 的每个后续请求中包含相同的属性,以便可以对用户进行身份验证并提供对受保护路由的访问权限
因此,包含凭据的 Axios 请求应如下所示:
\nawait axios.post(url, data, {withCredentials: true}))\nRun Code Online (Sandbox Code Playgroud)\n请求中的等效项fetch()(即使用Fetch API)是credentials: \'include\'。credentials的默认值为same-origin。使用credentials: \'include\'将导致浏览器在同源和跨源请求中包含凭据,并设置在跨源响应中发回的任何 cookie。例如:
fetch(\'https://example.com\', {\n credentials: \'include\'\n});\nRun Code Online (Sandbox Code Playgroud)\n由于您正在执行跨源请求,因此要使上述任一方法正常工作,您需要显式指定允许的来源,如本答案中所述(在幕后,即设置Access-Control-Allow-Origin响应标头)。例如:
origins = [\'http://localhost:3000\', \'http://127.0.0.1:3000\',\n \'https://localhost:3000\', \'https://127.0.0.1:3000\'] \nRun Code Online (Sandbox Code Playgroud)\n相反,使用通配符*意味着允许所有来源;但是,这也只允许某些类型的通信,不包括涉及 的所有内容credentials,例如cookie、授权标头等\xe2\x80\x94,因此,您不应使用通配符*。
另外,请确保allow_credentials=True在使用CORSMiddleware( 将Access-Control-Allow-Credentials响应标头设置为true)。
示例(参见此处):
\napp.add_middleware(\n CORSMiddleware,\n allow_origins=origins,\n allow_credentials=True,\n allow_methods=["*"],\n allow_headers=["*"],\n)\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4858 次 |
| 最近记录: |