ทำให้ Axios ส่งคุกกี้ในคำขอโดยอัตโนมัติ


121

ฉันกำลังส่งคำขอจากไคลเอนต์ไปยังเซิร์ฟเวอร์ Express.js โดยใช้ Axios

ฉันตั้งค่าคุกกี้บนไคลเอนต์และฉันต้องการอ่านคุกกี้นั้นจากคำขอของ Axios ทั้งหมดโดยไม่ต้องเพิ่มคุกกี้ด้วยตนเองเพื่อขอด้วยมือ

นี่คือตัวอย่างคำขอไคลเอ็นต์ของฉัน:

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

ฉันพยายามเข้าถึงส่วนหัวหรือคุกกี้โดยใช้คุณสมบัติเหล่านี้ในเซิร์ฟเวอร์ Express.js ของฉัน:

req.headers
req.cookies

ไม่มีคุกกี้ใด ๆ ฉันใช้มิดเดิลแวร์ตัวแยกวิเคราะห์คุกกี้:

app.use(cookieParser())

ฉันจะทำให้ Axios ส่งคุกกี้ในคำขอโดยอัตโนมัติได้อย่างไร

แก้ไข:

ฉันตั้งค่าคุกกี้บนไคลเอนต์ดังนี้:

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:'/'})
        }
      })
    }
...

แม้ว่าจะใช้ Axios แต่ก็ไม่เกี่ยวข้องกับคำถาม ฉันแค่ต้องการฝังคุกกี้ลงในคำขอทั้งหมดของฉันเมื่อตั้งค่าคุกกี้แล้ว


1
คุณตั้งค่าคุกกี้บนไคลเอนต์ได้อย่างไร? แสดงโค้ดตัวอย่างได้โปรด :)
Tzook Bar Noy

@TzookBarNoy เพิ่มรหัสในคำถาม
Kunok

คุกกี้ถูกตั้งค่าโดยเซิร์ฟเวอร์โดยที่ Set-Cookie ไม่ใช่ไคลเอนต์ฉันเดาว่าคุณหมายถึงการอ่านคุกกี้บนไคลเอนต์ ตามโปรโตคอลคุกกี้ไคลเอ็นต์ควรรวมส่วนหัวของคุกกี้ในคำขอไปยังเซิร์ฟเวอร์ผู้ออกคุกกี้
Hans Poo

คำตอบ:


247

ฉันมีปัญหาเดียวกันและได้รับการแก้ไขโดยใช้withCredentialsคุณสมบัติ

XMLHttpRequest จากโดเมนอื่นไม่สามารถตั้งค่าคุกกี้สำหรับโดเมนของตนเองได้เว้นแต่ว่า withCredentials จะถูกตั้งค่าเป็น true ก่อนที่จะทำการร้องขอ

axios.get('some api url', {withCredentials: true});

8
หากคุณพยายามเชื่อมต่อกับแอป Express - คุณจะต้องใช้ cors และใช้การตั้งค่าเหล่านี้ ต้องระบุที่มาของคำขอ app.use (cors ({ข้อมูลประจำตัว: จริงที่มา: ' localhost: 8080 '}));
DogCoffee

17
โปรดทราบว่าสิ่งนี้จะใช้ได้เฉพาะเมื่อAccess-Control-Allow-Originไม่ได้ตั้งค่าส่วนหัวในการตอบกลับเป็นสัญลักษณ์แทน (*)
Jerry Zhang

1
@JerryZhang คุณหมายถึงอะไร? ฉันกำลังประสบปัญหาเดียวกันหากAccess-Control-Allow-Originไม่ได้ตั้งค่า*ไว้ฉันจะไม่ส่งคำขอไปยังเซิร์ฟเวอร์นั้นเนื่องจาก CORS ถูกต้อง
samayo

5
การตอบสนองต้องตั้งAccess-Control-Allow-Originค่าเป็นโดเมนที่คุณต้องการส่งคำขอ XHR เช่นhttps://a.comเป็นเซิร์ฟเวอร์ที่https://b.comเป็นลูกค้าและhttps://b.comมีการโหลดในเบราว์เซอร์ของใครบางคนและใช้เพื่อให้การร้องขอไปยังXMLHTTPRequest https://a.comนอกจากนี้สำหรับXMLHTTPRequest(เริ่มต้นในhttps://a.com) เพื่อตั้งค่าwithCredential: trueเซิร์ฟเวอร์ - https://b.comยังต้องได้รับการกำหนดค่าเพื่อให้ส่วนหัวของการตอบกลับมีAccess-Control-Allow-Origin: https://a.com
เจอร์รี่จาง

ฉันมีปัญหาเล็กน้อยกับสิ่งนี้ ... ถ้าฉันมี as server b เป็นไคลเอนต์ (เช่นหน้า react) กว่าที่ฉันตั้งค่านี้เป็นจริงมันจะส่งข้อมูลประจำตัวไม่ใช่ข้อมูลรับรอง b ... ฮ่า ๆ .. ตกลงมันไม่ตลก
golddragon007

26

TL; DR:

{ withCredentials: true } หรือ axios.defaults.withCredentials = true


จากเอกสาร axios

withCredentials: false, // default

withCredentials ระบุว่าควรส่งคำขอการควบคุมการเข้าถึงข้ามไซต์โดยใช้ข้อมูลประจำตัวหรือไม่

หากคุณผ่าน{ withCredentials: true }คำขอของคุณควรใช้งานได้

วิธีที่ดีกว่าจะได้รับการตั้งค่าwithCredentialsเป็นtrueในaxios.defaults

axios.defaults.withCredentials = true


5
การส่งหนังสือรับรองทุกครั้งถือเป็นการปฏิบัติที่ไม่ดี มีการควบคุมเหล่านี้ด้วยเหตุผล การพูดคุยกับบริการอื่นการส่งคุกกี้ทั้งหมดของคุณ - ไม่ว่าจะไม่ถูกใช้งานก็เต็มไปด้วยการแสวงหาประโยชน์
colm.anseo

2
@colminator เฉพาะคุกกี้ที่มีโดเมนเซิร์ฟเวอร์เป็นโดเมนเท่านั้นที่จะถูกส่ง (โดยค่าเริ่มต้นจะไม่ถูกส่งไปยังโดเมนย่อยใด ๆ และอาจมีการกรองเพิ่มเติมตามเส้นทาง) เราจะส่งเฉพาะคุกกี้ของเซิร์ฟเวอร์ที่เซิร์ฟเวอร์กำหนดเท่านั้น
M3RS

15

ฉันไม่คุ้นเคยกับ Axios แต่เท่าที่ฉันรู้ในจาวาสคริปต์และ ajax มีตัวเลือก

withCredentials: true

การดำเนินการนี้จะส่งคุกกี้ไปยังฝั่งไคลเอ็นต์โดยอัตโนมัติ ตัวอย่างเช่นสถานการณ์นี้สร้างขึ้นด้วย passportjs ซึ่งตั้งค่าคุกกี้บนเซิร์ฟเวอร์


11

สิ่งสำคัญคือต้องตั้งค่าส่วนหัวที่จำเป็นในการตอบกลับด่วน นี่คือสิ่งที่เหมาะกับฉัน:

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();
});

การเพิ่มX-PINGOTHERเข้าเป็นสิ่งที่Access-Control-Allow-Headersจำเป็นสำหรับฉัน (Node.js 6.9 พร้อม Express 4.16, Chrome 63) ตรวจสอบโพสต์ของJakeElderเกี่ยวกับปัญหา GitHub นี้: github.com/axios/axios/issues/191#issuecomment-311069164
Frosty Z


5

สำหรับคนที่ยังแก้ไม่ได้คำตอบนี้ช่วยฉันได้ คำตอบ stackoverflow: 34558264

TLDR; จำเป็นต้องตั้งค่า{withCredentials: true}ในคำขอ GET ทั้งสองเช่นกันคำขอ POST (รับคุกกี้) สำหรับทั้งสองแกนและการดึงข้อมูล


1
นี่เป็นสิ่งสำคัญ ฉันมองข้ามสิ่งนี้ไปในโค้ดของฉันและใช้เวลาพอสมควรสงสัยว่าทำไม{ withCredentials: true }ในคำขอ GET ถึงไม่มีผลใด ๆ
yogmk

1
สำคัญมาก ๆ! มีการอภิปรายมากมายเกี่ยวกับการเพิ่มwithCredentials: trueในการกำหนดค่าคำขอ แต่ไม่ใช่รายละเอียดนี้ ฉันใช้เวลาเกือบ 2 วันในการพยายามแก้ปัญหาจนมาเจอสิ่งนี้
rantao

4

ฉันจะทำให้ Axios ส่งคุกกี้ในคำขอโดยอัตโนมัติได้อย่างไร

ชุด axios.defaults.withCredentials = true;

หรือสำหรับคำขอเฉพาะบางอย่างที่คุณสามารถใช้ได้ axios.get(url,{withCredentials:true})

สิ่งนี้จะทำให้เกิดข้อผิดพลาด CORS หาก 'Access-Control-Allow-Origin' ของคุณถูกตั้งค่าเป็นสัญลักษณ์แทน (*) ดังนั้นโปรดระบุ url ต้นทางของคำขอของคุณ

เช่น: หากส่วนหน้าของคุณซึ่งทำให้คำขอทำงานบน localhost: 3000 ให้ตั้งค่าส่วนหัวการตอบกลับเป็น

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

ยังตั้ง

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

3

ดังนั้นฉันจึงมีปัญหาเดียวกันนี้และเสียชีวิตไปประมาณ 6 ชั่วโมงในการค้นหาฉันมี

withCredentials: true

แต่เบราว์เซอร์ยังคงไม่บันทึกคุกกี้จนกระทั่งด้วยเหตุผลแปลก ๆ ฉันมีความคิดที่จะสับเปลี่ยนการตั้งค่า:

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

ดูเหมือนว่าคุณควรส่งคีย์ 'withCredentials' ก่อนเสมอ


3

คุณสามารถใช้withCredentialsคุณสมบัติเพื่อส่งผ่านคุกกี้ในคำขอ

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

โดยการตั้งค่า{ withCredentials: true }คุณอาจพบปัญหาข้ามแหล่งกำเนิด เพื่อแก้ปัญหาที่คุณต้องใช้

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

คุณสามารถอ่านเกี่ยวกับwithCredentials ได้ที่นี่


2

คุณกำลังคิดทั้งสองอย่างผสมกัน

คุณมี "react-cookie" และ "axios"

react-cookie => ใช้สำหรับจัดการคุกกี้ทางฝั่งไคลเอ็นต์

axios => ใช้สำหรับส่งคำขอ ajax ไปยังเซิร์ฟเวอร์

ด้วยข้อมูลดังกล่าวหากคุณต้องการให้คุกกี้จากฝั่งไคลเอ็นต์ถูกสื่อสารในด้านแบ็กเอนด์ด้วยคุณจะต้องเชื่อมต่อคุกกี้เข้าด้วยกัน

หมายเหตุจาก Readme "react-cookie":

คุกกี้ Isomorphic!

เพื่อให้สามารถเข้าถึงคุกกี้ของผู้ใช้ในขณะที่ทำการแสดงผลเซิร์ฟเวอร์คุณสามารถใช้ plugToRequest หรือ setRawCookie

ลิงค์ไปยัง readme

หากนี่คือสิ่งที่คุณต้องการเยี่ยมมาก

ถ้าไม่โปรดแสดงความคิดเห็นเพื่อให้ฉันได้อธิบายเพิ่มเติม


ทำอะไรplugToRequestกันแน่? ฉันคิดว่าจะเข้าถึงคุกกี้บนเซิร์ฟเวอร์โหนดสิ่งเดียวที่ต้องการคือcookie-parserมิดเดิลแวร์ (สมมติว่า Express)?
geoboy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.