2010-08-02 30 views
7

Tất cả mọi thứ hoạt động hoàn hảo trong Firefox và Chrome nhưng ngoại trừ trong IE8 (8.0.6001.18702)IE8 XSS/Jquery vấn đề

Đây là mã kiểm tra (Jquery 1.4.2) (cùng một vấn đề với $ .post):

$(function() { 
    $.get("http://domain2.tld/some.php", {}, function(response) { 
     alert(response); 
    }); 
}); 

mã này được thực hiện trong domain1.tld và nó được nạp từ domain2.tld, theo cách này:

<script type="text/javascript" src="http://domain2.tld/test.js"></script> 

tôi nhận được một "Permission denied" tin nhắn trong IE8. Tôi đã cố gắng cho đến nay nhưng không thành công:

1) thêm trong domain1.tld (mã php):

header("X-XSS-Protection: 0"); 

2) vô hiệu hóa bộ lọc XSS trong các tùy chọn IE8.

Tôi đang sử dụng IE8 debugger và nó hiển thị lỗi trong dòng 5113:

xhr.open(type, s.url, s.async); 

Nếu thay vì gọi $ .get (domain2.tld ...), tôi gọi $ .get (domain1. tld ...) không có lỗi, xác nhận với tôi rằng đó là một vấn đề "chính sách nguồn gốc" của XSS.

Giải pháp duy nhất của tôi (tôi nghĩ) đang thực hiện thông qua proxy (mã php) nhưng tôi không muốn làm điều đó vì nó tác động đến hiệu suất.

Có ai đó biết về cách thay thế/khắc phục sự cố này không?

Lưu ý: Cập nhật IE8 không phải là một tùy chọn vì tôi muốn kiểm tra nó mà không cần cập nhật.

Một vấn đề rất giống với tôi: http://forum.jquery.com/topic/jquery-ui-tabs-ie8-and-injecting-elements-into-dom

Trả lời

5

(Tôi khuyên bạn nên kiểm tra danh sách tôi gửi trước câu trả lời này)

Để tạo điều kiện cho quá trình này, tôi đã plugin CORS và sửa đổi nó. Bạn sẽ không cần sửa đổi mã Jquery hiện tại nếu bạn chỉ sử dụng $ .get và $ .post. Tôi đã thử nghiệm nó trong IE8 và nó hoạt động như mong đợi. Đối với phần còn lại của các trình duyệt sẽ sử dụng các cuộc gọi JQuery bình thường. Bạn thậm chí có thể thêm mã này theo yêu cầu (với các thẻ có điều kiện). Đọc các nhận xét ban đầu để biết thêm thông tin. Tôi hy vọng nó sẽ giúp ...

Đây là mã (lưu nó ví dụ như jquery.xdomain.js):

/* 
* XDR (non-XHR) extension functions for IE8+ 
* Based in CORS plugin (http://plugins.jquery.com/project/cors) 
* Modified by A.Lepe (www.alepe.com, Aug 2010) 
* 
* It supports calls using $.get and $.post only. 
* The main difference between the CORS plugin and this one are: 
* 
* 1) This method tries first to use XDR and if not available 
* will try to use XHR. This is to prevent any alert or 
* security message from IE. 
* 
* 2) To minimize size and target only IE8+ versions, this method 
* does not provides an alternative fall-back. 
* CORS version uses proxy_xmlhttp.js as fall-back option (see link #1 below). 
* 
* If you want to support "OLD" browsers, an alternative fall-back 
* can be easily implemented (instead the error alert). 
* For example, something like: 
* 
* ... 
* } catch(e) { 
* data["proxy_url"] = url; 
* $._get(proxy, data, callback, type); 
* } 
* ... 
* 
* in which "proxy" must be a URL where your proxy is located. 
* Your proxy may look like: 
* 
* <?php 
    //GET method example: 
    $URL = $_GET["proxy_url"]; 
    unset($_GET["proxy_url"]); 
    $params = http_build_query($_GET); 
    echo file_get_contents($URL."?".$params)); 
* ?> 
* 
* For POST method you may check link #2. 
* 
* NOTES: 
* 
* $.post() method it might not work as expected. XDR does 
* not send the data to the server in the same way XHR do 
* (am I missing something?). In order to have access to that 
* POST data you will need to: 
* 
* a) set: 
*  always_populate_raw_post_data = On 
*  register_long_arrays = On 
* 
* OR : 
* 
* b) import it manually (see link #3): 
    //-------- Import XDR POST data --------- 
    if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) { 
     $data = explode('&', $GLOBALS["HTTP_RAW_POST_DATA"]); 
     foreach ($data as $val) { 
      if (!empty($val)) { 
       list($key, $value) = explode('=', $val); 
       $_POST[$key] = urldecode($value); 
      } 
     } 
    } 
* 
* Remember to add the respective headers in the server that will 
* allow the XDR calls: 
     header('Access-Control-Allow-Origin: *'); //Or http://example.com 
     header('Access-Control-Max-Age: 3628800'); 
     header('Access-Control-Allow-Methods: GET, POST'); 
*/ 
(function($) { 
$._get = $.get; 
$._post = $.post; 
$.get = function (url, data, callback, type) { 
    // try XDR 
    if (jQuery.browser.msie && window.XDomainRequest) { 
     var params = ''; 
     for (var key in data) { 
      params += ((params || url.indexOf("?") != -1)?'&':'?')+key+'='+data[key]; 
     } 
     // Use Microsoft XDR 
     var xdr = new XDomainRequest(); 
     xdr.open("GET", url+params); 
     xdr.onload = function() { 
      callback(this.responseText, 'success'); 
     }; 
     xdr.send(); 
    } else { 
     try { 
      // Try using jQuery to get data 
      $._get(url, data, callback, type); 
     } catch(e) { 
      alert(e.message); 
     } 
    } 
} 
$.post = function (url, data, callback, type) { 
    // Try XDR 
    if (jQuery.browser.msie && window.XDomainRequest) { 
     var params = ''; 
     for (var key in data) { 
      params += (params?'&':'')+key+'='+data[key]; 
     } 
     // Use XDR 
     var xdr = new XDomainRequest(); 
     xdr.open("POST", url); 
     xdr.send(params); 
     xdr.onload = function() { 
      callback(xdr.responseText, 'success'); 
     }; 
    } else { 
     try { 
      // Try using jQuery to POST 
      $._post(url, data, callback, type); 
     } catch(e) { 
      alert(e.message); 
     } 
    } 
} 
})(jQuery); 

Links:

+0

Cảm ơn bạn vì điều này! Tuy nhiên, trong việc sử dụng điều này cho một chút của một trường hợp cạnh gần đây, tôi phát hiện ra rằng nó hơi phá vỡ các chức năng bản địa của '$ .get' và' $ .post', mà mỗi trả về một đối tượng jqXHR. Điều này có thể dễ dàng sửa bằng cách sửa đổi các khối try trong mã của bạn để đọc 'return $ ._ get (url, dữ liệu, gọi lại, type);' và 'return $ ._ post (url, data, callback, type);' – itsmequinn

-1

Tôi sẽ phải đồng ý với jAndy đây, nó rất không chắc bạn đã nhận nó làm việc ở tất cả. Chính sách gốc tương tự được áp dụng (http://en.wikipedia.org/wiki/Same_origin_policy), đặt cược tốt nhất của bạn là viết một proxy cục bộ mà các cuộc thăm dò tập lệnh của bạn thăm dò, sau đó cho phép proxy thực hiện các cuộc gọi tên miền chéo.

8

Tôi xin lỗi nếu tiếng Anh của tôi không phải là hoàn hảo, như tôi có thể nhìn thấy tôi đã không đủ rõ ràng ... Một trong những mối quan tâm chính của tôi được giải thích bởi người khác ở đây: http://http://forum.jquery.com/topic/cross-domain-ajax-and-ie

Vì vậy, những gì thay thế tồn tại?

1) XDomainRequest

Cá nhân tôi nghĩ rằng đây là cách tốt nhất để thực hiện cross-site scripting trong IE8 + (vì nó được hỗ trợ natively). Vấn đề duy nhất là đó là cách duy nhất của Microsoft. Nhưng như nhiều thứ khác với gia đình IE, chúng ta có thể dễ dàng mở rộng chức năng ajax của JQuery.

Theo tài liệu, bạn sẽ cần chỉ định một số tiêu đề bổ sung trong miền1.tld, for example, in PHP như thế này:

header("Access-Control-Allow-Origin: http://domain2.tld"); //use * for any 

Có thể giải pháp thay thế tiếp theo hữu ích để cung cấp việc thực hiện jquery của XDomainRequest;

Cập nhật (a): Có một (không jquery) mà "thay thế" lớp XHR để làm cho nó qua trình duyệt XDR library, nó có trụ sở tại pmxdr client library. Tôi chưa thử.

2) CORS

Vấn đề duy nhất với plugin này là không chính xác một phần mở rộng như các chức năng của nó được đặt tên khác nhau, vì vậy bạn cần phải thay đổi mã của bạn hoặc quấn plugin.

Cập nhật (b): Tôi đã sửa đổi plugin CORS để dễ dàng hơn. Kiểm tra câu trả lời khác của tôi để lấy mã.

3) JsonP in JQuery

này nên là cách dễ nhất để giải quyết vấn đề của tôi (như tôi có quyền kiểm soát của cả hai máy chủ). Thực tế, hầu hết các trình duyệt đều hỗ trợ tính năng tạo trang web chéo, chỉ khi định dạng json được sử dụng (tôi tin rằng xml cũng có thể được sử dụng). Trong trường hợp này, hàm $ .getJSON() được sử dụng. Để làm cho nó hoạt động, bạn cần xác định (như trạng thái tài liệu) callback =? trong URL, ví dụ:

$.getJSON("http://domain2.tld/index.php?callback=?",funciton(res){ ... }); 

"?" sau khi "gọi lại" sẽ được thay thế bằng một định danh ... trong file php của bạn, bạn cần phải nhận định đó và bao quanh mã Json như thế này:

print_r($_GET["callback"])."(".json_encode($mydata).");"; 

(tôi rằng ví dụ từ here)

Vấn đề với phương pháp này là nếu bạn muốn truy xuất HTML chỉ, nó phải nằm bên trong một đối tượng json và do đó làm cho quá trình phức tạp hơn một chút và áp đảo.

4) jquery.jsonp plugin

Nếu bạn cần kiểm chứng thực thêm và các tính năng hỗ trợ JSONP mẹ đẻ trong JQuery, sau đó thử plugin này mà cũng sẽ đơn giản hóa quá trình này.

5) xdomainajax

Plugin này sử dụng một aproach thú vị sử dụng dịch vụ của Yahoo YQL, trong đó bất kỳ trang web (hoặc một phần của nó) có thể được chuyển đổi sang Json, làm cho nó có thể để nhập nó vào javascript. Phương pháp này là tốt cho những tình huống mà bạn không thể thay đổi định dạng gốc.

6) flXHR

Giải pháp này sử dụng flash (swf) để đạt được sự kỳ diệu. Tôi có thể nói rằng đây là một cách rất nhanh chóng để đạt được gần như một thực hiện hoàn toàn qua trình duyệt (vì nó dựa vào hỗ trợ flash). Phương pháp này có thể là lý tưởng cho những trang web trong đó flash sẽ có mặt (chắc chắn). Tuy nhiên, nếu trang web của bạn không yêu cầu flash, thì điều đó trở thành bất lợi chính khi người dùng cần phải cài đặt flash theo thứ tự này để hoạt động.

7) xdajax

Giải pháp này có trụ sở tại thực hiện YUI cùng với cách tiếp cận "Flash".

8) Nếu không có tùy chọn nào trước đó tốt cho bạn, hãy nhớ rằng bạn vẫn có thể sử dụng thủ thuật chèn thẻ cũ để nhập mã JS.

9) Giảm mức bảo mật IE xuống mức tối thiểu cũng giải quyết được sự cố. Nhưng tôi nghĩ sẽ không tốt nếu có một thông điệp như thế này: "Hãy hạ thấp cài đặt bảo mật của bạn để sử dụng trang này" ... lol

Tôi hy vọng điều này có thể giúp những người khác trong tình huống tương tự.

+0

Viết tuyệt vời. –