Hướng dẫn cors php - cors php
Hôm nay, chúng tôi sẽ hướng dẫn cho bạn cách cho phép yêu cầu CORS cho nhiều nguồn khác nhau trong PHP. Show
Như chúng ta đã biết thì CORS (Cross Origin Resource Sharing) là một tính năng mới được tích hợp trong HTML5, thêm vào các HTTP headers chỉ dẫn cho trình duyệt web về sử dụng và quản lý nội dung cross-domain, cho phép lấy dữ liệu từ một trang khác thông qua XMLHttpRequest.CORS (Cross Origin Resource Sharing) là một tính năng mới được tích hợp trong HTML5, thêm vào các HTTP headers chỉ dẫn cho trình duyệt web về sử dụng và quản lý nội dung cross-domain, cho phép lấy dữ liệu từ một trang khác thông qua XMLHttpRequest. Để nhận được phản hồi từ một yêu cầu POST có nhiều nguồn gốc khác nhau , chúng ta cần bao gồm tiêu đề $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3. Đặc điểm kỹ thuật của $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3cho phép nhiều nguồn gốc hoặc giá trị $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.5hoặc ký tự đại diện $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.6. Ví dụ
Để bật CORS cho nhiều tên miền thì chúng ta sẽ sử dụng mã sau: Ví dụ
Để bật CORS cho nhiều tên miền thì chúng ta sẽ sử dụng mã sau: $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.8 để xác minh miền mà yêu cầu đến và sau đó đặt có điều kiện $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3. Trong đoạn mã trên, chúng tôi đã lấy một mảng gồm nhiều tên miền mà chúng tôi muốn cho phép $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.7.Sử dụng biến $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.8 để xác minh miền mà yêu cầu đến và sau đó đặt có điều kiện $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3. Tôi hy vọng bạn thấy bài viết này hữu ích.Bài viết này đã giúp ích cho bạn?Cors là gì? Vai trò của Cors? Nó là một nhu cầu rất thông dụng với các developer web đó là truy truy vấn qua API. Tuy nhiên, việc truy vấn và xử lý dữ liệu từ API nhiều khi cũng rất khó khăn. Rất nhiều lập trình viên phải đối mặt với các vấn đề liên quan đến CORS. Vậy CORS là gì? Và lý do tại sao chúng ta cần CORS? CORS là một cơ chế cho phép nhiều tài nguyên khác nhau (fonts, Javascript, v.v…) của một trang web có thể được truy vấn từ domain khác với domain của trang đó. CORS là viết tắt của từ Cross-origin resource sharing. là một cơ chế cho phép nhiều tài nguyên khác nhau (fonts, Javascript, v.v…) của một trang web có thể được truy vấn từ domain khác với domain của trang đó. CORS là viết tắt của từ Cross-origin resource sharing. Đây chính là lỗi CORS policy mà bất cứ lập trình viên nào cũng sẽ gặp phải. Khi call API tới server mà không có header $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3 hoặc giá trị của nó không hợp lệ thì sẽ phát sinh lỗi này và không lấy được dữ liệu từ API. Cách khắc phục lỗi trên là phải config enable CORS lên để phía client có thể gọi được dữ liệu. Các bạn có thể tham khảo cách để enable với các ngôn ngữ tại đây Enable CORS on ServerCORS lên để phía client có thể gọi được dữ liệu. Các bạn có thể tham khảo cách để enable với các ngôn ngữ tại đây Enable CORS on Server Tại sao chúng ta cần CORSCORS được sinh ra là vì same-origin policy, là một chính sách liên quan đến bảo mật được cài đặt vào toàn bộ các trình duyệt hiện nay. Chính sách này ngăn chặn việc truy cập tài nguyên của các domain khác một cách vô tội vạ. Ta có ví dụ một kịch bản như sau:
Same-origin policy chính là để ngăn chặn những kịch bản như trên để bảo vệ người dùng, giúp an toàn hơn khi lướt web. Bạn có thể thử trên web console và sẽ nhận được lỗi ngay: $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Truy cập URL trên từ bất kỳ domain nào ngoài const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }2 bạn cũng sẽ nhận được lỗi như vậy. Đó chính là nhờ same-origin policy. Thế nhưng trong thế giới web, lập trình viên thường xuyên phải thực hiện truy vấn đến các domain khác, đặc biệt là khi làm việc với các API. Đó là lúc chúng ta cần đến CORS. CORS sử dụng các HTTP header để “thông báo” cho trình duyệt rằng, một ứng dụng web chạy ở origin này (thường là domain này) có thể truy cập được các tài nguyên ở origin khác (domain khác).CORS. CORS sử dụng các HTTP header để “thông báo” cho trình duyệt rằng, một ứng dụng web chạy ở origin này (thường là domain này) có thể truy cập được các tài nguyên ở origin khác (domain khác). Một ứng dụng web sẽ thực hiện truy vấn HTTP cross-origin nếu nó yêu cầu đến các tài nguyên ở origin khác với origin nó đang chạy (khác giao thức, domain, port). Sự khác biệt về giao thức ở đây là khác biệt kiểu như HTTP với FTP chứ không phải HTTP và HTTPS (dù nhiều trình duyệt không cho phép trộn lẫn các tài nguyên truy cập bằng HTTP và HTTPS nhưng đó là vấn đề khác, không liên quan đến CORS). Các trường hợp cần đến CORS rất phổ biến trong thực tế. Một ví dụ rất điển hình như sau: một ứng dụng web chạy ở domain const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }3 và nó cần truy vấn đến const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }4 để lấy một vài dữ liệu (thường được thực hiện bởi JavaScript bằng cách sử dụng XMLHttpRequest). Các trình duyệt đều cài đặt same-origin policy và tuân thủ nó rất chặt chẽ. Cài đặt XMLHttpRequest và kể cả Fetch API cũng đều tuân thủ chính sách này. Do đó những truy vấn như ở trên sẽ không thu được kết quả gì, trừ khi máy chủ trả về response có các header CORS phù hợp. Như vậy, bằng việc sử dụng CORS, chúng ta có thể thúc đẩy việc giao tiếp trong ứng dụng web dễ dàng hơn rất nhiều. Các truy vấn dùng CORSCác truy vấn sau bắt buộc phải sử dụng CORS, theo tiêu chuẩn quốc tế.
Làm thế nào để sử dụng CORSMột hiểu lầm khá phổ biến, nhất là với các lập trình viên mới làm việc với API lại được làm việc với API của các hãng lớn, tài liệu đầy đủ, đó là cho rằng CORS là công việc của frontend. Nhưng thực ra CORS hoàn toàn là công việc của backend.
Về phía máy chủ, sau khi có được thông tin về nguồn gốc của truy vấn, nó có thể lựa chọn không phải hồi truy vấn đó, trả về lỗi hoặc trả về dữ liệu cần thiết. Trong trường hợp trả về dữ liệu, máy chủ cần thiết lập các HTTP header sao cho trình duyệt hiểu rằng truy vấn đó đã được chấp nhận. Như vậy, chúng ta có thể thấy rằng, CORS giúp thúc đấy quá trình trao đổi dữ liệu giữa trình duyệt và máy chủ. CORS hoàn toàn không có liên quan gì đến việc trao đổi trực tiếp giữa ứng dụng web mà một máy chủ web khác, ví dụ backend của ứng dụng đó truy cập đến tài nguyên trên một origin khác, nó cũng không cần đến CORS. Tạo truy vấn CORS bằng XMLHttpRequestTrong phần này chúng ta sẽ tìm hiểu cách tạo ra các truy vấn CORS bằng JavaScript. CORS được hỗ trợ bởi hầu hết các trình duyệt hiện đại. Riêng với IE, nó chỉ hỗ trợ từ IE 8 trở lên mà thôi. Tạo truy vấnCác trình duyệt Chrome, Firefox, Safari đều sử dụng version mới của XMLHttpRequest do đó việc truy vấn CORS diễn ra hết sức thuận lợi. IE thì sử dụng XDomainRequest, nó hoạt động gần giống với XMLHttpRequest nhưng có nhiều hạn chế hơn. Chúng ta có thể bắt đầu bằng cách tạo ra các object cần thiết. Dưới đây là một đoạn code như thế: const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); } Sau khi tạo được đối tượng XMLHttpRequest rồi thì chúng ta cần một số event handler, trong trường hợp này, chúng ta chỉ cần quan tâm 2 event const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }8 và const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }9 là đủ. Ngoài ra còn một số event khác như request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }0, request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }1 không được sử dụng nhiều lắm. request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); } Thực ra các trình duyệt khác nhau lại có cách cài đặt rất khác nhau với event const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }9. Ví dụ, Firefox trả về status là 0 và request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }3 luôn rỗng với mọi lỗi. Ngoài ra, các trình duyệt cũng thường không cho phép truy cập đến nội dung cụ thể của lỗi đã xảy ra, chúng ta chỉ biết rằng đã có lỗi mà thôi. withCredentialsMặc định, các truy vấn CORS không gửi hoặc thiết lập bất cứ cookie nào trên trình duyệt. Nếu muốn sử dụng cookie trong truy vấn đó, chúng ta phải đặt thuộc tính request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }4 của truy vấn bằng request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }5: xhr.withCredentials = true; Tuy nhiên, đó cũng mới chỉ là một nửa mà thôi. Nửa còn lại thuộc về phía máy chủ, đó là HTTP header request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }6 phải là true (chúng ta sẽ tìm hiểu ở phần sau). Với giá trị request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }4 bằng request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }5, cookie sẽ được tự động thêm vào cũng như thiết lập nếu có phản hồi từ máy chủ. Lưu ý rằng, cookie trong trường hợp này là third-party cookie và việc lưu trữ, truy cập cookie vẫn hoàn toàn thuân theo same-origin policy, do đó, chúng ta không thể truy cập cookie bằng request.onload = () => { const responseText = request.responseText; console.log(responseText); } request.onerror = () => { console.log('Error'); }9 được. Nó hoàn toàn được xử lý tự động bởi trình duyệt. Gửi truy vấnSau khi mọi việc đã hoàn tất, việc cuối cùng chúng ta cần làm là gửi truy vấn đi nữa mà thôi: request.send(); Lúc này truy vấn sẽ được gửi đến máy chủ, và nếu máy chủ đó chấp nhận CORS thì nó sẽ trả về response tương ứng. Hoạt động của truy vấn lúc này hoàn toàn giống với truy vấn có chúng origin thông thường. Tạo truy vấn CORS bằng jQueryHàm xhr.withCredentials = true;0 của jQuery có thể được sử dụng cho các truy vấn thông thường lẫn truy vấn CORS (cookie cũng được hỗ trợ mặc định). Do đó nếu sử dụng jQuery thì công việc của lập trình viên cũng khá dễ dàng. Tuy nhiên, cần lưu ý một số điều như sau:
Dưới đây là một đoạn code sử dụng jQuery để tạo truy vấn CORS: $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } }) Tạo truy vấn CORS bằng Fetch APIChúng ta cũng có thể sử dụng Fetch API để tạo truy vấn CORS. Tuy nhiên, xhr.withCredentials = true;4 mới chỉ xuất hiện từ ES6 nên nhiều trình duyệt vẫn chưa hỗ trợ nó (cụ thể là IE tất cả các phiên bản đều không hỗ trợ). Fetch API cho chúng ta một phương thức đơn giản để tạo các truy vấn, và nó đã cài đặt sẵn việc hỗ trợ CORS nên chúng ta cũng có thể thao tác rất đơn giản, giống như jQuery vậy. Tuy nhiên, kết quả trả về của xhr.withCredentials = true;4 là một Promise do đó các thao tác xử lý kết quả sẽ khác nhiều jQuery. Xem thêm nên học gì khi dùng jQuery. Lập trình với fetch rất đơn giản, thậm chí còn đơn giản hơn của với jQuery: fetch('https://jsonplaceholder.typicode.com/posts/1') .then(response => response.json()) .then(console.log) Cấu hình máy chủ hỗ trợ CORSĐây là phần phức tạp nhất, cũng là phần quan trọng nhất đối với CORS. Như đã nói ở trên, thực ra việc hỗ trợ CORS hay không phụ thuộc hoàn toàn vào máy chủ chứ không phải client. Có hai loại truy vấn CORS: loại truy vấn “đơn giản” và “không đơn giản”. Một truy vấn đơn giản hoàn toàn không cần đến CORS preflight. Một truy vấn sẽ được gọi là đơn giản nếu nó thoả mãn những điều kiện sau:
Những truy vấn này được gọi là “đơn giản” bởi chúng có thể được coi là truy vấn thông thường từ trình duyệt mà không cần đến CORS, giống như submit một form HTML thông thường chẳng hạn. Những truy vấn không phải “đơn giản” sẽ là truy vấn không đơn giản, và chúng cần CORS preflight. CORS preflight có nghĩa là trước khi truy vấn được gửi, nó cần phải gửi một truy vấn trước bằng phương thức request.send();9. Mục đích của truy vấn “preflight” này là nhằm kiểm tra xem truy vấn thực sự có an toàn để gửi và nhận hay không. Đối với truy vấn đơn giảnMột truy vấn CORS đơn giản như đã nói ở trên, có thể có gói tin HTTP dạng như sau: GET /cors HTTP/1.1 Origin: https://api.topdevvn.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/... Với các phương thức khác, gói tin HTTP cũng tương tự như vậy. Lưu ý rằng, một truy vấn CORS hợp lệ luôn luôn có const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }7 ở trong header. Giá trị của header này hoàn toàn được thiết lập tự động bởi trình duyệt, và không ai có thể thay đổi nó được. Giá trị của header này sẽ bao gồm scheme ( $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })1), domain ( $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })2) và cổng (trong trường hợp dùng cổng mặc định thì không cần, ví dụ http dùng cổng 80). Giá trị của header chính là biểu thị nguồn gốc của truy vấn.
Ví dụ, Firefox không có header này cho các truy vấn same origin nhưng Chrome và Safari vẫn thêm header nay khi truy vấn same origin nhưng sử dụng các phương thức xhr.withCredentials = true;8, $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })5 hoặc $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })6. Đây là một diểm cần lưu ý với các lập trình viên backend, vì nếu không để ý có thể không thêm origin của chính app trong danh sách các domain được chấp nhận, điều đó khiến cho chính truy vấn same origin lại gặp lỗi. Dưới đây là response của máy chủ phản hồi cho một truy vấn CORS hợp lệ: 0Tất cả các header liên quan đến CORS đều có phần đầu tiên là $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })7. Ý nghĩa của từng header như sau:
Đối với truy vấn cần preflightKhông phải truy vấn nào cũng là đơn giản do việc trao đổi dữ liệu giữa trình duyệt và máy chủ diễn ra rất đa dạng. Các phương thức $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })5 hay $.ajax({ type: 'GET', url: 'https://jsonplaceholder.typicode.com/posts/1', success: data => { console.log(data); }, error: () => { console.log('Error'); } })6 cũng thường xuyên được sử dụng. Ngoài ra kiểu dữ liệu JSON ( fetch('https://jsonplaceholder.typicode.com/posts/1') .then(response => response.json()) .then(console.log)9) cũng là lựa chọn của nhiều lập trình viên. Trong những trường hợp như vậy, trước khi truy vấn chính được thực hiện thì một truy vấn gọi là preflight sẽ được gửi đi trước. Ở phía frontend, các truy vấn đơn giản hay phức tạp đều trông sẽ giống nhau. Truy vấn preflight hoàn toàn được thực hiện ngầm và trong suốt với người dùng. Truy vấn preflight sẽ được gửi đi trước nhằm xác định xem truy vấn thực sự có thể thực hiện được hay không. Sau khi có được phản hồi tích cực, trình duyệt sẽ gửi truy vấn thực sự. Kết quả của truy vấn preflight có thể được cache nên nó không cần phải thực hiện cho mọi truy vấn. Dưới đây là một gói tin HTTP cho truy vấn preflight: 1Tương tự như truy vấn đơn giản, truy vấn này cũng tự động được thêm header const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }7. Truy vấn preflight sẽ được thực hiện bằng phương thức request.send();9 với một số header đặc thù:
Truy vấn preflight là một cách để hỏi máy chủ rằng, liệu truy vấn thực sự có thể thực hiện được hay không. Mà máy chủ dựa vào hai header này để quyết định xem có chấp nhận truy vấn hay không. Nếu chấp nhận, máy chủ sẽ phản hồi như sau: 2Trong đó, response có thể có những header như sau:
Một khi truy vấn preflight có được phản hồi và được chấp nhận, trình duyệt sẽ thực hiện truy vấn thực sự. Truy vấn lúc này tương tự như truy vấn CORS đơn giản và quá trình xử lý cũng như phản hồi hoàn toàn tương tự như vậy.
Về phía client, nếu trong trường hợp không thực hiện được truy vấn, event const createCORSRequest = (method, url) => { let xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // Kiểm tra XMLHttpRequest object có thuộc tính // withCredentials hay không // Thuộc tính này chỉ có ở XMLHttpRequest2 xhr.open(method, url, true); } else if (typeof XDomainRequest != 'undefined') { // Kiểm tra XDomainRequest // Đây là đối tượng chỉ có ở IE và // là cách để IE thực hiện truy vấn CORS xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } const request = createCORSRequest('GET', 'https://jsonplaceholder.typicode.com/posts/1'); if (!request) { throw new Error('CORS is not supported'); }9 sẽ được gọi. Tuy nhiên, như đã nó ở trên, trình duyệt cũng không thể truy cập được nhiều thông tin về lỗi đó, chỉ đơn giản là biết có lỗi mà thôi. Hỗ trợ CORS của các frameworkLaravel CORSKhi chúng ta code vài ứng dụng dưới local mà có connect tới Laravel backed, thì bạn sẽ nhận cái thông báo error CORS ngay. Vì vậy cần tạo một middleware sau: 3Sau đó update header trong 01 4Sau đó, đăng ký middleware trong 02 5Nếu bạn muốn bật CORS bất kỳ route nào, chỉ cần add middleware này trong route registration. Ngoài ra bạn có thể dùng packgage ngoài tại /laravel-cors./laravel-cors. Xem thêm việc làm Laravel lương cao lên đến 3000 USDviệc làm Laravel lương cao lên đến 3000 USD CORS NodejsChúng ta sử dụng dòng code dưới đây để set một header trên response của bạn để bật CORS: 6Bật CORS cho toàn bộ resource trên server 7Chỉ định file nào đó 8Ví dụ đầy đủ: 9Ruby on RailsRuby on Rails cho phép chúng ta thiết lập cũng như thay đổi các header trong response khá dễ dàng, do đó, muốn chấp nhận truy vấn CORS, chúng ta có thể đơn giản là làm như sau: $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.0 Tham khảo thêm các việc làm Ruby on Rails cho bạnviệc làm Ruby on Rails cho bạn DjangoVới Django chúng ta phải sử dụng thêm một package, đó là Django CORS headers. Package này sẽ giúp chúng ta thiết lập các header cần thiết cho một truy vấn CORS, đồng thời cho chúng ta khả năng cấu hình URL nào cho phép CORS, URL nào thì không. Với package này, chúng ta có thể cấu hình sao cho chỉ có API mới hỗ trợ CORS như sau: $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.1 Ngoài ra còn rất nhiều cấu hình khác nữa, cho phép chúng ta chỉ chấp nhận truy vấn CORS từ một vài origin nhất định chẳng hạn ( 03). Nội dung chi tiết xin mới các bạn xem cụ thể tại README của package đó.Xem thêm các vị trí tuyển dụng lập trình Django lương cao FlaskTương tự như Django, với Flask, chúng ta cũng phải sử dụng thêm một package, đó là Flask-CORS mới có thể chấp nhận các truy vấn CORS được. $.get('https://facebook.com/messages') Access to XMLHttpRequest at 'https://facebook.com/messages' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.2 Kết luậnTrên đây là tất cả những gì cơ bản để bạn biết CORS là gì, cách nó giúp các ứng dụng web dễ dàng hơn trong việc trao đổi thông tin cũng như hiển thị nội dung, tăng khả năng tương tác giữa các dịch vụ trên Internet. Hy vọng bài viết giúp ích cho mọi người trong quá trình làm việc. Có thể bạn muốn xem thêm:
Xem thêm việc làm IT tại TopDev! |