Sau khi đăng nhập qua $.ajax()
một trang web, tôi đang cố gắng gửi $.ajax()
yêu cầu thứ hai đến trang web đó - nhưng khi tôi kiểm tra các tiêu đề được gửi bằng FireBug, không có cookie phiên nào được đưa vào yêu cầu.
Tôi đang làm gì sai?
Sau khi đăng nhập qua $.ajax()
một trang web, tôi đang cố gắng gửi $.ajax()
yêu cầu thứ hai đến trang web đó - nhưng khi tôi kiểm tra các tiêu đề được gửi bằng FireBug, không có cookie phiên nào được đưa vào yêu cầu.
Tôi đang làm gì sai?
Câu trả lời:
Cuộc gọi AJAX chỉ gửi Cookies nếu url bạn đang gọi nằm trên cùng một tên miền với tập lệnh gọi của bạn.
Đây có thể là một vấn đề tên miền chéo.
Có thể bạn đã cố gọi một url từ www.domain-a.com
khi tập lệnh gọi của bạn được bật www.domain-b.com
(Nói cách khác: Bạn đã thực hiện Cuộc gọi tên miền chéo trong trường hợp trình duyệt sẽ không gửi bất kỳ cookie nào để bảo vệ quyền riêng tư của bạn).
Trong trường hợp này, các tùy chọn của bạn là:
Vui mừng nếu điều đó giúp một chút.
path=/something
và bạn đang yêu cầu trang /another
thì cookie sẽ không được gửi. Khi bạn yêu cầu trang /something
, cookie sẽ được gửi như mong đợi. Vì vậy, kiểm tra mã đặt cookie là tốt.
Tôi đang hoạt động trong kịch bản tên miền chéo. Trong quá trình đăng nhập, máy chủ từ xa đang trả về tiêu đề Set-Cookie cùng với Access-Control-Allow-Credentials
được đặt thành true.
Cuộc gọi ajax tiếp theo đến máy chủ từ xa sẽ sử dụng cookie này.
CORS Access-Control-Allow-Credentials
có mặt để cho phép đăng nhập tên miền chéo. Kiểm tra https://developer.mozilla.org/En/HTTP_access_control để biết ví dụ.
Đối với tôi, nó có vẻ như là một lỗi trong JQuery (hoặc ít nhất là tính năng tương tự trong phiên bản tiếp theo).
CẬP NHẬT:
Cookies không được đặt tự động từ phản hồi AJAX (trích dẫn: http://aleembawany.com/2006/11/14/anatomy-of-a-well-design-ajax-login-experience/ )
Tại sao?
Bạn không thể nhận giá trị của cookie từ phản hồi để đặt thủ công ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader )
Tôi bối rối..
Cần tồn tại một cách để yêu cầu jquery.ajax()
thiết lập XMLHttpRequest.withCredentials = "true"
tham số.
TRẢ LỜI:
Bạn nên sử dụng xhrFields
param của http://api.jquery.com/jQuery.ajax/
Ví dụ trong tài liệu là:
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
Điều quan trọng là máy chủ trả lời chính xác cho yêu cầu này. Sao chép ở đây những bình luận tuyệt vời từ @ Frédéric và @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: *
Vì vậy, khi yêu cầu là:
Origin: http://foo.example
Cookie: pageAccess=2
Máy chủ sẽ phản hồi với:
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
[payload]
Nếu không, tải trọng sẽ không được trả lại cho tập lệnh. Xem: 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/
Sử dụng
xhrFields: { withCredentials:true }
như một phần của lệnh gọi ajax jQuery của tôi chỉ là một phần của giải pháp. Tôi cũng cần phải trả lại các tiêu đề trong phản hồi TÙY CHỌN từ tài nguyên của mình:
Access-Control-Allow-Origin : http://www.wombling.com
Access-Control-Allow-Credentials : true
Điều quan trọng là chỉ có một "nguồn gốc" được phép nằm trong tiêu đề phản hồi của lệnh gọi TÙY CHỌN chứ không phải "*". Tôi đã đạt được điều này bằng cách đọc nguồn gốc từ yêu cầu và đưa nó trở lại phản hồi - có thể tránh được lý do ban đầu cho sự hạn chế, nhưng trong trường hợp sử dụng của tôi, bảo mật không phải là tối quan trọng.
Tôi nghĩ rằng đáng để đề cập rõ ràng yêu cầu chỉ có một nguồn gốc, vì tiêu chuẩn W3C không cho phép một danh sách được phân tách không gian - nhưng Chrome thì không! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB bit "trong thực tế".
Đặt cái này trong hàm init của bạn:
$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
Nó sẽ làm việc.
Đã có rất nhiều câu trả lời tốt cho câu hỏi này, nhưng tôi nghĩ có thể hữu ích để làm rõ trường hợp bạn muốn gửi cookie phiên vì tên miền cookie phù hợp, nhưng nó không được gửi vì yêu cầu AJAX là được thực hiện cho một tên miền phụ khác. Trong trường hợp này, tôi có một cookie được gán cho các * .mydomain.com miền, và tôi muốn nó được đưa vào một yêu cầu AJAX để different.mydomain.com ". Theo mặc định, các tập tin cookie không được gửi. Bạn không cần phải tắt HTTPONLY trên cookie phiên để giải quyết vấn đề này. Bạn chỉ cần thực hiện những gì đã đề nghị ( https://stackoverflow.com/a/23660618/545223 ) và làm như sau.
1) Thêm sau đây vào yêu cầu ajax của bạn.
xhrFields: { withCredentials:true }
2) Thêm phần sau vào tiêu đề phản hồi của bạn cho các tài nguyên trong tên miền phụ khác nhau.
Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true
Sau khi thử các giải pháp khác và vẫn không làm cho nó hoạt động, tôi đã tìm ra vấn đề trong trường hợp của tôi. Tôi đã thay đổi contentType từ "application / json" thành "text / plain".
$.ajax(fullUrl, {
type: "GET",
contentType: "text/plain",
xhrFields: {
withCredentials: true
},
crossDomain: true
});
Tôi đã gặp vấn đề tương tự và thực hiện một số kiểm tra kịch bản của tôi chỉ đơn giản là không nhận được cookie phiên.
Tôi đã tìm ra bằng cách xem giá trị cookie sessionid trong trình duyệt rằng khung của tôi (Django) đã vượt qua cookie sessionid với httpOnly làm mặc định. Điều này có nghĩa là các tập lệnh không có quyền truy cập vào giá trị sessionid và do đó không chuyển nó cùng với các yêu cầu. Thật là nực cười khi httpOnly sẽ là giá trị mặc định khi có rất nhiều thứ sử dụng Ajax yêu cầu hạn chế truy cập.
Để khắc phục điều này, tôi đã thay đổi cài đặt (SESSION_COOKIE_HTTPONLY = Sai) nhưng trong các trường hợp khác, đó có thể là cờ "HttpOnly" trên đường dẫn cookie
Nếu bạn đang phát triển trên localhost
hoặc một cổng trên localhost, chẳng hạn như localhost:8080
, ngoài các bước được mô tả trong các câu trả lời ở trên, bạn cũng cần đảm bảo rằng bạn không chuyển một giá trị miền trong tiêu đề Set-Cookie.
Bạn không thể đặt tên miền thành localhost
trong tiêu đề Set-Cookie - không chính xác - chỉ cần bỏ qua tên miền.
Xem Cookies trên localhost với tên miền rõ ràng và Tại sao asp.net không tạo cookie trong localhost?
Chỉ cần 2 xu của tôi khi đặt vấn đề cookie PHPSESSID khi trên localhost và trong môi trường dev. Tôi thực hiện cuộc gọi AJAX đến điểm cuối API REST của mình trên đầu máy. Nói địa chỉ của nó là mysite.localhost/api/member/login/
(máy chủ đạo đức trên môi trường dev của tôi).
Khi tôi thực hiện yêu cầu này trên Postman , mọi thứ sẽ ổn và PHPSESSID được đặt với phản hồi.
Khi tôi yêu cầu điểm cuối này qua AJAX từ trang được ủy quyền của Trình duyệt (ví dụ: 122.133.1.110:3000/test/api/login.php
trong dòng địa chỉ trình duyệt của tôi, hãy xem tên miền khác so với mysite.localhost
) PHPSESSID không xuất hiện giữa các cookie.
Khi tôi thực hiện yêu cầu này trực tiếp từ trang trên cùng một tên miền (nghĩa là mysite.localhost/test/api/login.php
) PHPSESSID được đặt tốt.
Vì vậy, đây là vấn đề cookie yêu cầu nguồn gốc xuất xứ chéo như được đề cập trong câu trả lời @flu ở trên
Thêm kịch bản và giải pháp của tôi trong trường hợp nó giúp người khác. Tôi gặp trường hợp tương tự khi sử dụng API RESTful. Máy chủ Web của tôi lưu trữ tệp HTML / Script / CSS và API hiển thị Máy chủ ứng dụng được lưu trữ trên cùng một tên miền. Tuy nhiên, con đường đã khác.
máy chủ web - mydomain / trang web /abc.html
đã sử dụng abc.js để đặt cookie có tên mycookie
máy chủ ứng dụng - mydomain / webapis / tên dịch vụ.
cuộc gọi api đã được thực hiện
Tôi đã mong đợi cookie trong mydomain / webapis / servicename và đã thử đọc nó nhưng nó không được gửi. Sau khi đọc nhận xét từ câu trả lời, tôi đã kiểm tra trong công cụ phát triển của trình duyệt rằng đường dẫn của mycookie được đặt thành "/ trang web " và do đó không có sẵn trong cuộc gọi dịch vụ tới
mydomain / webapis / servicename
Vì vậy, trong khi đặt cookie từ jquery, đây là những gì tôi đã làm -
$.cookie("mycookie","mayvalue",{**path:'/'**});
Có lẽ không trả lời 100% câu hỏi, nhưng tôi tình cờ gặp chủ đề này với hy vọng giải quyết vấn đề phiên khi ajax đăng tải một tập tin tải lên từ trình quản lý tài sản của trình soạn thảo đổi mới. Cuối cùng, giải pháp rất đơn giản: họ có một trình tải lên flash. Vô hiệu hóa điều đó (cài đặt
var flashUpload = false;
trong property.php) và đèn lại bắt đầu nhấp nháy.
Vì những vấn đề này có thể rất khó để gỡ lỗi, tôi thấy rằng việc đưa một cái gì đó như sau vào trình xử lý tải lên sẽ đưa bạn (tốt, tôi trong trường hợp này) đi đúng hướng:
$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");
Đi sâu vào nhật ký và tôi nhanh chóng phát hiện ra phiên bị mất, nơi không có cookie nào được gửi.
session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();
vậy, họ sẽ có được một thứ hoạt động