Tại sao lại Escape_javascript trước khi hiển thị một phần?


120

Tôi đang xem tập Railscast này và tự hỏi tại sao lại cần gọi tới escape_javascriptở đây:

$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");

Những gì được escape_javascriptsử dụng cho?

Theo tài liệu Rails :

Escape_javascript (javascript)

Trả lại nhà cung cấp dịch vụ thoát và các dấu ngoặc kép và đơn cho các phân đoạn JavaScript.

Nhưng điều đó không có nhiều ý nghĩa với tôi.


23
FYI, câu trả lời được chấp nhận ở đây không phải là câu trả lời chính xác. Kikito's là
Steve.

Câu trả lời:


-3

Bởi vì bạn không muốn người dùng đăng JavaScript mà trình duyệt thực sự thực thi?


4
Nhưng khi bạn muốn chuyển và hiển thị mã javascript thì sao?
berto77 22/02/12

Vâng, thực ra nó giống một phương pháp định dạng hơn. Nó không ngăn người dùng thực thi javascript của riêng họ. Không gì có thể ngăn cản điều đó.
LasagnaAndroid

3
Điều này không hữu ích. Xem câu trả lời kikito của thay thế.
nitsas

363

Sẽ dễ hiểu hơn nếu bạn chia mã thành hai phần.

Phần đầu tiên $("#reviews").append("<%= ... %>");là javascript với erb. Điều này có nghĩa là ý <%= ... %>muốn được thay thế bằng bất kỳ mã ruby ​​nào bên trong nó trả về. Kết quả của sự thay thế đó phải là javascript hợp lệ, nếu không nó sẽ gây ra lỗi khi máy khách cố gắng xử lý nó. Vì vậy, đó là điều đầu tiên: bạn cần javascript hợp lệ .

Một điều khác cần lưu ý là bất kỳ thứ gì ruby ​​tạo ra đều phải được chứa bên trong một chuỗi javascript có dấu ngoặc kép - hãy chú ý đến dấu ngoặc kép xung quanh <%= ... %>. Điều này có nghĩa là javascript được tạo sẽ giống như sau:

$("#reviews").append("...");

Bây giờ chúng ta hãy kiểm tra phần ruby ​​bên trong <%= ... %>. Làm gì render(:partial => @review)? Nó đang hiển thị một phần - có nghĩa là nó có thể hiển thị bất kỳ loại mã nào - html, css ... hoặc thậm chí nhiều javascript!

Vì vậy, điều gì sẽ xảy ra nếu một phần của chúng ta chứa một số html đơn giản, như đoạn này?

<a href="/mycontroller/myaction">Action!</a> 

Hãy nhớ rằng javascript của bạn đang sử dụng một chuỗi được trích dẫn kép làm tham số? Nếu chúng ta chỉ thay thế <%= ... %>mã bằng mã của phần đó, thì chúng ta gặp sự cố - ngay sau href=đó có một dấu ngoặc kép! Javascript sẽ không hợp lệ:

// Without escaping, you get a broken javascript string at href
$("#reviews").append("<a href="/mycontroller/myaction">Action!</a>");

Để điều này không xảy ra, bạn muốn thoát các ký tự đặc biệt này để chuỗi của bạn không bị cắt - thay vào đó bạn cần một thứ gì đó tạo ra điều này:

<a href=\"/mycontroller/myaction\">Action!</a>

Điều này làm gì escape_javascript. Nó đảm bảo rằng chuỗi được trả về sẽ không "phá vỡ" javascript. Nếu bạn sử dụng nó, bạn sẽ nhận được đầu ra mong muốn:

$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>")

Trân trọng!


4
thực sự, rất tốt lời giải thích cảm ơn bạn. Tôi đoán khi đó việc sử dụng 'Escape_javascript' sẽ gây hiểu lầm vì chúng tôi không thực sự sử dụng nó để thoát javascript thực. Bạn có thể đặt một thẻ script vào một phần và thực thi bất kỳ javascript nào bạn muốn.
Steve

13
@Steve đã đồng ý, một cái tên tốt hơn sẽ là escape_for_javascript, vì bạn thường thoát mã khác (html chẳng hạn) để nó không phá vỡ javascript.
kikito

14
escape_javascript()bây giờ có một phương thức ngắn hơn: simpley j()(ít nhất là trong Rails 4).
mjnissim

@kikito, sử dụng hiệu ứng này có phải tôi đang cố kết xuất một phần html có dạng từ xa không? Tôi đang cố gắng tìm hiểu lý do tại sao việc hiển thị một phần bằng javascript bao gồm một biểu mẫu khác sẽ gửi qua javascript khiến yêu cầu thứ hai là html thay vì js. Nếu bạn có thời gian, bạn có thể vui lòng xem câu hỏi tôi đã đăng về vấn đề này không? Cảm ơn! Câu hỏi của tôi
Jake Smith

1
@JakeSmith đã trả lời câu hỏi của bạn
kikito

8

người dùng có thể đăng mã độc hại (người dùng độc hại) mà nếu không thoát sẽ có khả năng bị thực thi, cho phép người dùng kiểm soát ứng dụng của bạn.

thử cái này:

<% variable = '"); alert("hi there' %>
$("#reviews").append("<%= variable %>");

không thực sự quen thuộc với cú pháp của rails, nhưng nếu bạn không thoát variablethì một hộp cảnh báo sẽ hiển thị và tôi không nghĩ đó là hành vi dự định.


8

Nếu bạn xem nguồn ở đây , nó sẽ rõ ràng hơn nhiều.

Hàm này thực hiện hai điều sau:

  1. Nó thay thế các ký tự trong chuỗi đầu vào bằng các ký tự được xác định trong JS_ESCAPE_MAP

    Mục đích của việc này là để đảm bảo rằng mã javascript được tuần tự hóa một cách chính xác mà không can thiệp vào chuỗi bên ngoài mà nó đang được nhúng. Ví dụ: nếu bạn có một chuỗi javascript trong dấu ngoặc kép thì tất cả các dấu ngoặc kép trong chuỗi ký tự phải nằm trong dấu nháy đơn để tránh mã bị hỏng.

  2. Hàm cũng kiểm tra xem chuỗi kết quả có an toàn trong html hay không. Nếu không phải thì nó thực hiện việc thoát cần thiết để đảm bảo rằng chuỗi trở thành html an toàn và trả về kết quả.

Khi bạn đang sử dụng Escape_javascript, nó thường được nhúng vào một chuỗi khác hoặc html hiện có một cách động. Bạn cần đảm bảo rằng làm điều này sẽ không làm cho toàn bộ trang của bạn không hiển thị.

Một số khía cạnh của phản hồi này đã được chỉ ra trong các phản hồi khác nhưng tôi muốn kết hợp tất cả các mục lại với nhau bao gồm sự khác biệt giữa thoát javascript và thoát html. Ngoài ra, một số phản hồi ám chỉ rằng chức năng này giúp tránh việc chèn tập lệnh. Tôi không nghĩ đó là mục đích của chức năng này. Ví dụ: trong bài đánh giá của bạn nếu bài đánh giá của bạn có cảnh báo ('xin chào'), chỉ cần thêm nó vào nút sẽ không kích hoạt cửa sổ bật lên. Bạn không nhúng nó vào một chức năng được kích hoạt khi tải trang hoặc thông qua một số sự kiện khác. Chỉ có cảnh báo ('xin chào') như một phần của html của bạn không có nghĩa là nó sẽ thực thi dưới dạng javascript.

Điều đó nói rằng tôi không phủ nhận rằng việc chèn kịch bản là không thể. Nhưng để tránh điều đó, bạn cần thực hiện các bước khi lấy dữ liệu người dùng và lưu trữ trong cơ sở dữ liệu của mình. Chức năng và ví dụ bạn đang cung cấp có liên quan đến việc hiển thị thông tin đã được lưu.

Tôi hy vọng điều này sẽ giúp và trả lời câu hỏi của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.