Faça Axios enviar cookies em suas solicitações automaticamente

121

Estou enviando solicitações do cliente para meu servidor Express.js usando Axios.

Eu defini um cookie no cliente e quero ler esse cookie de todas as solicitações do Axios sem adicioná-las manualmente para solicitar manualmente.

Este é o meu exemplo de solicitação do cliente:

axios.get(`some api url`).then(response => ...

Tentei acessar cabeçalhos ou cookies usando estas propriedades em meu servidor Express.js:

req.headers
req.cookies

Nenhum deles continha cookies. Estou usando o middleware de analisador de cookies:

app.use(cookieParser())

Como faço para que o Axios envie cookies nas solicitações automaticamente?

Editar:

Eu defino o cookie no cliente assim:

import cookieClient from 'react-cookie'

...
let cookie = cookieClient.load('cookie-name')
if(cookie === undefined){
      axios.get('path/to/my/cookie/api').then(response => {
        if(response.status == 200){
          cookieClient.save('cookie-name', response.data, {path:'/'})
        }
      })
    }
...

Embora também esteja usando Axios, não é relevante para a questão. Eu simplesmente quero incorporar cookies em todas as minhas solicitações assim que um cookie for definido.

Kunok
fonte
1
como você colocou o cookie no cliente? mostre o exemplo de código :)
Tzook Bar Noy
@TzookBarNoy Código adicionado em questão
Kunok
Os cookies são definidos por servidores com Set-Cookie e não pelo cliente, eu acho que você quer dizer ler o cookie no cliente. De acordo com o protocolo Cookie, o cliente deve incluir um cabeçalho de Cookie em suas solicitações ao servidor emissor do cookie.
Hans Poo

Respostas:

241

Eu tive o mesmo problema e resolvi usando o withCredentialsimóvel.

XMLHttpRequest de um domínio diferente não pode definir valores de cookie para seu próprio domínio, a menos que withCredentials seja definido como true antes de fazer a solicitação.

axios.get('some api url', {withCredentials: true});
fingerpich
fonte
8
Se você estiver tentando se conectar a um aplicativo Express - você precisará usar cors e usar essas configurações. A origem da solicitação é obrigatória. app.use (cors ({credentials: true, origin: ' localhost: 8080 '}));
DogCoffee de
17
observe que isso só funcionará quando o Access-Control-Allow-Origincabeçalho de resposta não estiver definido como curinga (*)
Jerry Zhang
1
@JerryZhang O que você quer dizer? Estou enfrentando o mesmo problema, se Access-Control-Allow-Originnão estiver definido para *isso significa que não vou fazer a solicitação para esse servidor por causa do CORS certo
samayo
5
A resposta precisa definir Access-Control-Allow-Origino valor do domínio do qual você deseja fazer a solicitação XHR. por exemplo, https://a.comé o servidor, https://b.comé o cliente, https://b.comestá carregado no navegador de alguém e está usando XMLHTTPRequestpara fazer uma solicitação https://a.com. Além de XMLHTTPRequest(iniciado em https://a.com) definir withCredential: true, o servidor - https://b.comtambém precisa ser configurado para que o cabeçalho de resposta contenhaAccess-Control-Allow-Origin: https://a.com
Jerry Zhang
Eu tenho um pequeno problema com isso ... se eu tiver a como servidor b como cliente (ou seja, página de reação), do que se eu definir isso como verdadeiro, ele enviará as credenciais a, não as credenciais b ... LOL. .. OK, não é engraçado.
golddragon007
24

TL; DR:

{ withCredentials: true } ou axios.defaults.withCredentials = true


Da documentação dos axios

withCredentials: false, // default

withCredentials indica se as solicitações de controle de acesso entre sites devem ou não ser feitas usando credenciais

Se você passar { withCredentials: true }com seu pedido, deve funcionar.

Uma maneira melhor seria definir withCredentialscomo trueemaxios.defaults

axios.defaults.withCredentials = true

Fatih Acet
fonte
5
Enviar credenciais com cada solicitação é uma prática ruim. Esses controles existem por um motivo. Conversar com outro serviço, enviar todos os seus cookies - sejam eles usados ​​ou não, é uma oportunidade de exploração.
colm.anseo
2
@colminator apenas os cookies que possuem o domínio do servidor como domínio serão enviados. (Por padrão, eles não serão enviados para nenhum subdomínio e pode haver mais filtragem com base no caminho.) Na verdade, estamos apenas enviando os cookies do servidor que foram definidos pelo servidor.
M3RS
15

Não estou familiarizado com o Axios, mas pelo que sei em javascript e ajax existe uma opção

withCredentials: true

Isso enviará automaticamente o cookie para o lado do cliente. Por exemplo, este cenário também é gerado com passportjs, que define um cookie no servidor

RITESH ARORA
fonte
11

Também é importante definir os cabeçalhos necessários na resposta expressa. Estes são os que funcionaram para mim:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', yourExactHostname);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});
Eyk Rehbein
fonte
Adicionar X-PINGOTHERem Access-Control-Allow-Headersfoi obrigatório para mim (Node.js 6.9 com Express 4.16, Chrome 63). Verifique a postagem de JakeElder sobre este problema no GitHub: github.com/axios/axios/issues/191#issuecomment-311069164
Frosty Z de
5

para as pessoas que ainda não conseguiram resolver, essa resposta me ajudou. resposta stackoverflow: 34558264

TLDR; é necessário definir {withCredentials: true}tanto na solicitação GET quanto na solicitação POST (obtendo o cookie) para ambos os axios, bem como buscar.

the_dangoria
fonte
1
Isso é crucial. Eu tinha esquecido isso em meu código e passei um bom tempo me perguntando por que a { withCredentials: true }solicitação GET não teve qualquer efeito.
Yogmk
1
Extremamente importante! Há muita discussão sobre como adicionar withCredentials: truea configuração da solicitação, mas não esse detalhe. Passei quase 2 dias tentando resolver o problema até que me deparei com isso
R. Antão
4

Como faço para que o Axios envie cookies nas solicitações automaticamente?

conjunto axios.defaults.withCredentials = true;

ou para algum pedido específico que você pode usar axios.get(url,{withCredentials:true})

isso gerará um erro CORS se 'Access-Control-Allow-Origin' estiver definido como curinga (*). Portanto, certifique-se de especificar o url de origem de sua solicitação

por exemplo: se o seu front-end que faz a solicitação for executado em localhost: 3000, defina o cabeçalho de resposta como

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

também definido

res.setHeader('Access-Control-Allow-Credentials',true);
prak
fonte
3

Você pode usar withCredentialspropriedade para passar cookies na solicitação.

axios.get(`api_url`, { withCredentials: true })

Ao definir, { withCredentials: true }você pode encontrar problemas de origem cruzada. Para resolver isso, você precisa usar

expressApp.use(cors({ credentials: true, origin: "http://localhost:8080" }));

Aqui você pode ler sobre withCredentials

Sunil Garg
fonte
2

Você está misturando os dois pensamentos.

Você tem "react-cookie" e "axios"

react-cookie => é para lidar com o cookie no lado do cliente

axios => é para enviar solicitações ajax para o servidor

Com essas informações, se você quiser que os cookies do lado do cliente sejam comunicados também no lado do back-end, você precisará conectá-los.

Nota do Leiame "react-cookie":

Cookies isomórficos!

Para poder acessar os cookies do usuário durante a renderização do servidor, você pode usar plugToRequest ou setRawCookie.

link para ler-me

Se é isso que você precisa, ótimo.

Se não, por favor, comente para que eu possa elaborar mais.

Tzook Bar Noy
fonte
O que plugToRequestexatamente faz? Pensei em acessar cookies no servidor de nó, tudo que se precisa é o cookie-parsermiddleware (assumindo Express)?
geoboy
2

Eu tive exatamente o mesmo problema e perdi cerca de 6 horas da minha vida procurando,

withCredentials: true

Mas o navegador ainda não salvou o cookie até que, por algum motivo estranho, tive a ideia de embaralhar a definição de configuração:

Axios.post(GlobalVariables.API_URL + 'api/login', {
        email,
        password,
        honeyPot
    }, {
        withCredentials: true,
        headers: {'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'
    }});

Parece que você deve sempre enviar a chave 'withCredentials' primeiro.

Luigi Cordoba Granera
fonte