FastAPI no devuelve cookies a la interfaz de React

Resuelto jabodom934 asked hace 1 año • 1 respuestas

¿Por qué FastAPI no devuelve la cookie a mi interfaz, que es una aplicación React?

Aquí está mi código:

@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"}  

Cuando inicio sesión desde los autodocs de Swagger UI, puedo ver la cookie en los encabezados de respuesta usando DevTools en el navegador Chrome. Sin embargo, cuando inicio sesión desde mi aplicación React, no se devuelve ninguna cookie. Estoy usando axios para enviar la solicitud de esta manera:

await axios.post(login_url, formdata)

jabodom934 avatar Oct 05 '22 22:10 jabodom934
Aceptado

Primero, cree la cookie, como se muestra en el ejemplo siguiente, y asegúrese de que no se devuelva ningún error al realizar la solicitud POST de Axios y de que obtenga una 'status': 'success'respuesta con 200el código de estado. Es posible que también desee echar un vistazo a esta respuestamax_age , que también explica cómo usar las banderas y expires.

from fastapi import FastAPI, Response

app = FastAPI()

@app.get('/')
def main(response: Response):
    response.set_cookie(key='token', value='some-token-value', httponly=True) 
    return {'status': 'success'}

En segundo lugar, como mencionaste que estás usando React en el frontend, que debe estar escuchando en un puerto diferente al usado para el backend FastAPI, lo que significa que estás realizando solicitudes CORS , debes configurar la withCredentialspropiedad en true(por defecto esto está configurado en false), para permitir recibir/enviar credenciales, como cookies y encabezados de autenticación HTTP , desde/hacia otros orígenes. Dos servidores con el mismo dominio y protocolo, pero diferentes puertos , por ejemplo, se consideran orígenes diferentes (consulte la documentación de FastAPI en CORS y esta respuesta , que proporciona detalles sobre las cookies en general, así como soluciones para configurar cookies entre dominios, que usted en realidad no es necesario en su caso, ya que el dominio es el mismo tanto para el backend como para el frontend y, por lo tanto, configurar la cookie como de costumbre funcionaría bien).http://localhost:8000http://localhost:3000

Tenga en cuenta que si accede a su interfaz de React escribiendo http://localhost:3000en la barra de direcciones de su navegador, entonces sus solicitudes de Axios al backend de FastAPI deben usar el localhostdominio en la URL, por ejemplo, axios.post('http://localhost:8000',...y no axios.post('http://127.0.0.1:8000',... , ya que localhosty 127.0.0.1son dos dominios diferentes y, por lo tanto, De lo contrario, la cookie no se crearía para el localhostdominio, ya que se crearía para 127.0.0.1, es decir, el dominio utilizado en la axiossolicitud (y luego, ese sería el caso de las cookies entre dominios, como se describe en la respuesta vinculada anteriormente). que nuevamente, en su caso, no sería necesario).

Por lo tanto, para aceptar las cookies enviadas por el servidor, debe utilizarlas withCredentials: trueen su solicitud de Axios; de lo contrario, las cookies se ignorarán en la respuesta (que es el comportamiento predeterminado, cuando withCredentialsestá configurado en false; por lo tanto, se evita que diferentes dominios establezcan cookies para su propio dominio). La misma withCredentials: truepropiedad debe incluirse en cada solicitud posterior a su API, si desea que la cookie se envíe al servidor, para que el usuario pueda autenticarse y proporcionar acceso a rutas protegidas.

Por lo tanto, una solicitud de Axios que incluya credenciales debería verse así:

await axios.post(url, data, {withCredentials: true}))

El equivalente en una fetch()solicitud (es decir, usando Fetch API ) es credentials: 'include'. El valor predeterminado para credentialses same-origin. El uso credentials: 'include'hará que el navegador incluya credenciales tanto en solicitudes del mismo origen como de orígenes cruzados, así como también establecerá cualquier cookie enviada de vuelta en respuestas de orígenes cruzados. Por ejemplo:

fetch('https://example.com', {
  credentials: 'include'
});

Nota IMPORTANTE

Dado que está realizando una solicitud de origen cruzado, para que lo anterior funcione, deberá especificar explícitamente los orígenes permitidos, como se describe en esta respuesta (entre bastidores, es decir, configurar el Access-Control-Allow-Originencabezado de respuesta). Por ejemplo:

origins = ['http://localhost:3000', 'http://127.0.0.1:3000',
           'https://localhost:3000', 'https://127.0.0.1:3000'] 

Usar el *comodín en su lugar significaría que se permiten todos los orígenes; sin embargo, eso también permitiría solo ciertos tipos de comunicación, excluyendo todo lo que involucre credentials, como cookies , encabezados de autorización , etc.; por lo tanto, no debe usar el *comodín.

Además, asegúrese de configurarlo allow_credentials=Truecuando utilice CORSMiddleware(que establece el Access-Control-Allow-Credentialsencabezado de respuesta en true).

Ejemplo (ver aquí ):

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
Chris avatar Oct 05 '2022 17:10 Chris