Patrzę na ten odcinek Railscast i zastanawiam się, dlaczego escape_javascript
tutaj potrzebne jest wezwanie :
$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");
Do czego escape_javascript
służy?
Zgodnie z dokumentacją Rails :
escape_javascript (javascript)
Escape Carrier zwraca oraz pojedyncze i podwójne cudzysłowy dla segmentów JavaScript.
Ale to niewiele dla mnie znaczy.
Odpowiedzi:
Ponieważ nie chcesz, aby użytkownicy publikowali JavaScript, który faktycznie wykonuje przeglądarka?
źródło
Łatwiej jest to zrozumieć, jeśli podzielisz kod na dwie części.
Pierwsza część
$("#reviews").append("<%= ... %>");
to javascript z erb. Oznacza to, że<%= ... %>
zostanie zastąpiony przez kod ruby w środku, który zwróci. Wynik tej zamiany musi być prawidłowym skryptem javascript, w przeciwnym razie zgłosi błąd, gdy klient spróbuje go przetworzyć. To pierwsza rzecz: potrzebujesz prawidłowego javascript .Inną rzeczą, którą należy wziąć pod uwagę, jest to, że wszystko, co generuje ruby, musi być zawarte w łańcuchu javascript z podwójnymi cudzysłowami - zwróć uwagę na podwójne cudzysłowy wokół
<%= ... %>
. Oznacza to, że wygenerowany javascript będzie wyglądał następująco:Teraz przyjrzyjmy się rubinowej części wewnątrz pliku
<%= ... %>
. Co robirender(:partial => @review)
? To renderowanie częściowe - co oznacza, że może renderować dowolny rodzaj kodu - html, css ... lub nawet więcej javascript!Więc co się stanie, jeśli nasz podrzędny fragment zawiera prosty kod HTML, taki jak ten?
Pamiętasz, że Twój javascript przyjmował jako parametr ciąg znaków w podwójnych cudzysłowach? Jeśli po prostu zastąpimy go
<%= ... %>
kodem tej części, to mamy problem - zaraz po tymhref=
jest podwójny cudzysłów! JavaScript nie będzie prawidłowy:Aby tak się nie stało, chcesz uniknąć tych znaków specjalnych, aby łańcuch nie został przecięty - potrzebujesz czegoś, co zamiast tego wygeneruje:
To co
escape_javascript
robi. Zapewnia, że zwracany ciąg nie „zepsuje” javascript. Jeśli go użyjesz, uzyskasz pożądane wyjście:Pozdrowienia!
źródło
escape_for_javascript
, ponieważ często uciekasz przed innym kodem (na przykład html), aby nie zepsuć javascript.escape_javascript()
ma teraz krótszą metodę: simpleyj()
( przynajmniej w Rails 4).użytkownicy mogą wysyłać złośliwy kod (złośliwi użytkownicy), który pozostawiony bez zmiany znaczenia zostanie potencjalnie wykonany, umożliwiając użytkownikom kontrolowanie aplikacji.
Spróbuj tego:
niezbyt zaznajomiony ze składnią railsów, ale jeśli nie uciekniesz
variable
, pojawi się okienko ostrzegawcze i nie sądzę, aby było to zamierzone zachowanie.źródło
Jeśli spojrzysz na źródło tutaj , będzie znacznie jaśniejsze.
Ta funkcja realizuje następujące dwie rzeczy:
Zastępuje znaki w ciągu wejściowym znakami zdefiniowanymi w JS_ESCAPE_MAP
Ma to na celu upewnienie się, że kod javascript jest poprawnie serializowany bez zakłócania zewnętrznego ciągu, w którym jest osadzany. Na przykład, jeśli masz ciąg javascript w podwójnych cudzysłowach, wszystkie cudzysłowy w literałach ciągów muszą być w apostrofach, aby uniknąć zerwania kodu.
Kiedy używasz escape_javascript, zwykle jest on osadzany dynamicznie w innym łańcuchu lub istniejącym html. Musisz się upewnić, że wykonanie tej czynności nie spowoduje, że cała strona nie zostanie wyrenderowana.
Niektóre aspekty tej odpowiedzi zostały wskazane w innych odpowiedziach, ale chciałem zebrać wszystkie elementy razem, w tym różnicę między ucieczką javascript a ucieczką HTML. Ponadto niektóre odpowiedzi wspominają, że ta funkcja pomaga uniknąć wstrzyknięcia skryptu. Nie sądzę, że jest to celem tej funkcji. Na przykład w Twojej recenzji, jeśli Twoja recenzja zawiera alert („Cześć”), samo dołączenie go do węzła nie spowoduje uruchomienia wyskakującego okienka. Nie osadzasz go w funkcji, która jest wyzwalana podczas ładowania strony lub przez inne zdarzenie. Samo ostrzeżenie („cześć”) jako część kodu HTML nie oznacza, że będzie on wykonywany jako javascript.
To powiedziawszy, nie zaprzeczam, że wstrzyknięcie skryptu nie jest możliwe. Ale aby tego uniknąć, musisz podjąć kroki podczas pobierania danych użytkownika i przechowywania ich w bazie danych. Funkcja i przykład, które podajesz, są związane z renderowaniem informacji, które zostały już zapisane.
Mam nadzieję, że to pomoże i odpowie na Twoje pytanie.
źródło