หลังจากเข้าสู่ระบบผ่านทาง$.ajax()
เว็บไซต์ฉันพยายามส่ง$.ajax()
คำขอที่สองไปยังเว็บไซต์นั้น แต่เมื่อฉันตรวจสอบส่วนหัวที่ส่งโดยใช้ FireBug จะไม่มีคุกกี้เซสชันรวมอยู่ในคำขอ
ผมทำอะไรผิดหรือเปล่า?
หลังจากเข้าสู่ระบบผ่านทาง$.ajax()
เว็บไซต์ฉันพยายามส่ง$.ajax()
คำขอที่สองไปยังเว็บไซต์นั้น แต่เมื่อฉันตรวจสอบส่วนหัวที่ส่งโดยใช้ FireBug จะไม่มีคุกกี้เซสชันรวมอยู่ในคำขอ
ผมทำอะไรผิดหรือเปล่า?
คำตอบ:
AJAX โทรศัพท์จะส่งคุกกี้หาก url ที่คุณโทรอยู่นั้นอยู่ในโดเมนเดียวกับสคริปต์การโทรของคุณ
นี่อาจเป็นปัญหาข้ามโดเมน
บางทีคุณอาจพยายามโทรหา url www.domain-a.com
ในขณะที่สคริปต์การโทรของคุณเปิดอยู่www.domain-b.com
(กล่าวอีกนัยหนึ่ง: คุณทำการโทรข้ามโดเมนในกรณีนี้เบราว์เซอร์จะไม่ส่งคุกกี้ใด ๆ เพื่อปกป้องความเป็นส่วนตัวของคุณ)
ในกรณีนี้ตัวเลือกของคุณคือ:
ดีใจถ้ามันช่วยได้นิดหน่อย
path=/something
และคุณกำลังร้องขอหน้า/another
จากนั้นคุกกี้จะไม่ถูกส่ง เมื่อคุณร้องขอหน้า/something
คุกกี้จะถูกส่งไปตามที่คาดไว้ ดังนั้นตรวจสอบรหัสที่ตั้งค่าคุกกี้ด้วย
ฉันทำงานในสถานการณ์ข้ามโดเมน ระหว่างการล็อกอินรีโมตเซิร์ฟเวอร์กำลังส่งคืนส่วนหัว Set-Cookie พร้อมกับAccess-Control-Allow-Credentials
ตั้งค่าเป็นจริง
การโทร ajax ครั้งต่อไปไปยังเซิร์ฟเวอร์ระยะไกลควรใช้คุกกี้นี้
CORS Access-Control-Allow-Credentials
อยู่ที่นั่นเพื่ออนุญาตการบันทึกข้ามโดเมน ตรวจสอบhttps://developer.mozilla.org/En/HTTP_access_controlเพื่อดูตัวอย่าง
สำหรับฉันดูเหมือนว่าข้อบกพร่องใน JQuery (หรืออย่างน้อยคุณสมบัติที่จะเป็นในรุ่นถัดไป)
UPDATE:
คุกกี้ไม่ได้ถูกตั้งค่าโดยอัตโนมัติจากการตอบกลับ AJAX (การอ้างอิง: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/ )
ทำไม?
คุณไม่สามารถรับค่าคุกกี้จากการตอบสนองเพื่อตั้งค่าด้วยตนเอง ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader )
ฉันสับสน ..
ควรมีวิธีขอjquery.ajax()
ตั้งค่าXMLHttpRequest.withCredentials = "true"
พารามิเตอร์
คำตอบ:
คุณควรใช้xhrFields
พารามิเตอร์ของhttp://api.jquery.com/jQuery.ajax/
ตัวอย่างในเอกสารประกอบคือ:
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
สิ่งสำคัญคือเซิร์ฟเวอร์ต้องตอบคำขอนี้ให้ถูกต้อง คัดลอกความคิดเห็นที่ดีที่นี่จาก @ Frédéricและ @Pebbl:
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *
ดังนั้นเมื่อคำขอคือ:
Origin: http://foo.example
Cookie: pageAccess=2
เซิร์ฟเวอร์ควรตอบกลับด้วย:
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
[payload]
มิฉะนั้นส่วนของข้อมูลจะไม่ถูกส่งกลับไปที่สคริปต์ ดู: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *
developer.mozilla.org/en-US/docs/Web/HTTP/…
การใช้
xhrFields: { withCredentials:true }
ในฐานะที่เป็นส่วนหนึ่งของการโทร jQuery ajax ของฉันเป็นเพียงส่วนหนึ่งของโซลูชัน ฉันยังต้องให้ส่วนหัวกลับมาในการตอบสนองตัวเลือกจากทรัพยากรของฉัน:
Access-Control-Allow-Origin : http://www.wombling.com
Access-Control-Allow-Credentials : true
เป็นสิ่งสำคัญที่อนุญาต "แหล่งกำเนิด" หนึ่งเดียวเท่านั้นที่อยู่ในส่วนหัวการตอบสนองของการเรียก OPTIONS ไม่ใช่ "*" ฉันทำสิ่งนี้ได้โดยการอ่านที่มาจากคำร้องขอและเติมกลับเข้าไปในคำตอบ - อาจหลีกเลี่ยงเหตุผลดั้งเดิมสำหรับข้อ จำกัด แต่ในกรณีที่ใช้งานของฉันความปลอดภัยไม่ได้เป็นสิ่งสำคัญที่สุด
ฉันคิดว่ามันคุ้มค่าที่จะกล่าวถึงข้อกำหนดสำหรับแหล่งกำเนิดเดียวเท่านั้นเนื่องจากมาตรฐาน W3C ไม่อนุญาตให้มีรายการที่คั่นด้วยช่องว่าง - แต่ Chrome ไม่ได้! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB บิต "ในทางปฏิบัติ"
ใส่สิ่งนี้ในฟังก์ชั่น init ของคุณ:
$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
มันจะทำงาน.
มีคำตอบที่ดีสำหรับคำถามนี้อยู่แล้ว แต่ฉันคิดว่าอาจเป็นประโยชน์ในการชี้แจงกรณีที่คุณคาดว่าจะส่งคุกกี้เซสชันเนื่องจากโดเมนคุกกี้ตรงกัน แต่ไม่ได้รับเนื่องจากคำขอ AJAX เป็น ถูกทำให้เป็นโดเมนย่อยอื่น ในกรณีนี้ฉันมีคุกกี้ที่กำหนดให้กับโดเมน* .mydomain.comและฉันต้องการให้รวมอยู่ในคำขอ AJAX ไปยังdifferent.mydomain.com "โดยค่าเริ่มต้นคุกกี้จะไม่ได้รับการส่ง คุณไม่จำเป็นต้องปิดการใช้งาน HTTPONLY บนคุกกี้เซสชั่นเพื่อแก้ไขปัญหานี้คุณจะต้องทำสิ่งที่แนะนำให้ใช้ wombling ( https://stackoverflow.com/a/23660618/545223 ) และทำสิ่งต่อไปนี้
1) เพิ่มสิ่งต่อไปนี้ในคำขอ ajax ของคุณ
xhrFields: { withCredentials:true }
2) เพิ่มส่วนต่อไปนี้ในส่วนหัวการตอบกลับของคุณสำหรับทรัพยากรในโดเมนย่อยที่ต่างกัน
Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true
หลังจากลองใช้วิธีแก้ไขปัญหาอื่นและยังไม่สามารถใช้งานได้ฉันพบว่าปัญหาคืออะไรในกรณีของฉัน ฉันเปลี่ยน contentType จาก "application / json" เป็น "text / plain"
$.ajax(fullUrl, {
type: "GET",
contentType: "text/plain",
xhrFields: {
withCredentials: true
},
crossDomain: true
});
ฉันมีปัญหาเดียวกันนี้และทำการตรวจสอบบางอย่างสคริปต์ของฉันเป็นเพียงแค่ไม่ได้รับคุกกี้ sessionid
ฉันคิดออกโดยดูที่ค่าเซสชันคุกกี้ในเบราว์เซอร์ที่กรอบงานของฉัน (Django) ผ่านคุกกี้เซสชันที่มี HttpOnly เป็นค่าเริ่มต้น นี่หมายความว่าสคริปต์ไม่สามารถเข้าถึงค่า sessionid ดังนั้นจึงไม่ส่งผ่านไปพร้อมกับคำขอ ชนิดที่ไร้สาระที่ HttpOnly จะเป็นค่าเริ่มต้นเมื่อมีหลายสิ่งที่ใช้ Ajax ซึ่งจะต้องมีการ จำกัด การเข้าถึง
ในการแก้ไขปัญหานี้ฉันได้เปลี่ยนการตั้งค่า (SESSION_COOKIE_HTTPONLY = False) แต่ในกรณีอื่น ๆ อาจเป็นสถานะ "HttpOnly" บนเส้นทางคุกกี้
หากคุณกำลังพัฒนาlocalhost
หรือพอร์ตบน localhost เช่นlocalhost:8080
นอกเหนือจากขั้นตอนที่อธิบายไว้ในคำตอบข้างต้นคุณต้องให้แน่ใจว่าคุณไม่ได้ผ่านค่าโดเมนในส่วนหัว Set-Cookie
คุณไม่สามารถตั้งค่าโดเมนเป็นlocalhost
ในส่วนหัว Set-Cookie - ไม่ถูกต้อง - เพียงแค่ละเว้นโดเมน
ดูคุกกี้บน localhost ที่มีโดเมนชัดเจนและทำไม asp.net จะไม่สร้างคุกกี้ใน localhost
เพียง 2 เซ็นต์ของฉันในการตั้งค่าปัญหาคุกกี้ PHPSESSID เมื่อใน localhost และภายใต้สภาพแวดล้อมที่ dev ฉันโทร AJAX ไปยังปลายทาง REST API บน locahost บอกว่าที่อยู่ของมันคือmysite.localhost/api/member/login/
(โฮสต์ที่ดีในสภาพแวดล้อม dev ของฉัน)
เมื่อฉันทำคำขอนี้กับบุรุษไปรษณีย์สิ่งต่าง ๆ ดีและ PHPSESSID ถูกตั้งค่าด้วยการตอบสนอง
เมื่อฉันขอปลายทางนี้ผ่าน AJAX จากหน้าพร็อกซีของ Browsersync (เช่นจาก122.133.1.110:3000/test/api/login.php
ในบรรทัดที่อยู่ของเบราว์เซอร์ของฉันให้ดูโดเมนนั้นแตกต่างจาก vs mysite.localhost
) PHPSESSID ไม่ปรากฏในคุกกี้
เมื่อฉันขอนี้โดยตรงจากหน้าในโดเมนเดียวกัน (เช่นmysite.localhost/test/api/login.php
) PHPSESSID ตั้งค่าได้ดี
ดังนั้นนี่คือปัญหาคุกกี้คำขอข้ามต้นทางที่กล่าวถึงใน @flu คำตอบด้านบน
การเพิ่มสถานการณ์และโซลูชันของฉันในกรณีที่ช่วยเหลือคนอื่น ฉันพบกรณีที่คล้ายกันเมื่อใช้ RESTful API เว็บเซิร์ฟเวอร์ของฉันโฮสต์ไฟล์ HTML / Script / CSS และ Application Server ที่เปิดเผย APIs นั้นโฮสต์บนโดเมนเดียวกัน อย่างไรก็ตามเส้นทางนั้นแตกต่างกัน
เว็บเซิร์ฟเวอร์ - mydomain / หน้าเว็บ /abc.html
ใช้abc.jsซึ่งตั้งค่าคุกกี้ชื่อmycookie
เซิร์ฟเวอร์แอป - mydomain / webapis / servicename
สาย api ที่ถูกทำให้
ฉันคาดหวังว่าคุกกี้ใน mydomain / webapis / servicename และพยายามอ่านมัน แต่มันไม่ได้ถูกส่ง หลังจากอ่านความคิดเห็นจากคำตอบฉันตรวจสอบในเครื่องมือพัฒนาของเบราว์เซอร์ที่เส้นทางของ mycookie ถูกตั้งค่าเป็น "/ เว็บเพจ " และด้วยเหตุนี้จึงไม่สามารถใช้งานได้ในบริการโทรถึง
mydomain / webapis / servicename
ดังนั้นในขณะที่การตั้งค่าคุกกี้จาก jquery นี่คือสิ่งที่ฉันทำ -
$.cookie("mycookie","mayvalue",{**path:'/'**});
บางทีอาจจะไม่ตอบคำถาม 100% แต่ฉันก็สะดุดกับกระทู้นี้ด้วยความหวังว่าจะได้แก้ปัญหาเซสชันเมื่อ ajax โพสต์ไฟล์อัพโหลดจากผู้จัดการสินทรัพย์ของ ในที่สุดการแก้ปัญหาก็ง่าย: พวกเขามีแฟลชอัพโหลด ปิดการใช้งานนั้น (การตั้งค่า
var flashUpload = false;
ใน asset.php) และไฟก็เริ่มกระพริบอีกครั้ง
เนื่องจากปัญหาเหล่านี้อาจแก้ไขได้ยากมากฉันพบว่าการใส่สิ่งต่อไปนี้ในตัวจัดการการอัปโหลดจะทำให้คุณ (ถูกต้องฉันในกรณีนี้) ในการติดตามที่ถูกต้อง:
$sn=session_name();
error_log("session_name: $sn ");
if(isset($_GET[$sn])) error_log("session as GET param");
if(isset($_POST[$sn])) error_log("session as POST param");
if(isset($_COOKIE[$sn])) error_log("session as Cookie");
if(isset($PHPSESSID)) error_log("session as Global");
ดำดิ่งลงสู่ล็อกแล้วฉันก็พบเซสชั่นที่หายไปอย่างรวดเร็วซึ่งไม่มีการส่งคุกกี้
session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();
นี้พวกเขาจะได้รับสิ่งที่ใช้งานได้