2009-10-25 7 views
110

나는 this Railscast episode보고 escape_javascript에 대한 호출이 여기에 왜 필요한지 궁금하네요 :부분 렌더링 전에 escape_javascript를 사용해야하는 이유는 무엇입니까?

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

escape_javascript는 무엇을 사용합니까? the Rails docs에 따르면

:

escape_javascript (자바 스크립트)

탈출 캐리어 반품 및 단일 및 자바 스크립트 세그먼트 따옴표.

하지만 나에게별로 중요하지 않습니다.

+19

참고로 대답은 정답이 아닙니다. Kikito는 – Steve

답변

1

사용자가 브라우저에서 실제로 실행하는 JavaScript를 게시하지 않으니까?

+4

입니다.하지만 자바 스크립트 코드를 전달하고 렌더링하고 싶을 때는 어떻습니까? – berto77

+0

그래, 실제로 그것은 형식 지정 방법입니다.사용자가 자신의 javascript를 실행하는 것을 막지는 않습니다. 그걸 막을 수있는 것은 아무것도 없습니다. – Deviljho

+2

이것은 도움이되지 않습니다. 대신에 [kikito의 대답] (http://stackoverflow.com/a/1623813/703233)을 참조하십시오. – nitsas

8

사용자는 이스케이프 처리되지 않은 상태로두면 잠재적으로 실행되어 사용자가 응용 프로그램을 제어 할 수있는 악성 코드 (악성 사용자)를 게시 할 수 있습니다. 레일의 구문

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

정말 익숙하지 않은,하지만 당신은 variable를 탈출하지 않으면 다음 경고 상자가 표시됩니다, 그리고 난 그 의도 행동이라고 생각하지 말아 :

이 시도.

327

두 부분으로 코드를 분할하면 이해하기가 더 쉽습니다.

첫 번째 부분 $("#reviews").append("<%= ... %>");은 erb가있는 javascript입니다. 즉, <%= ... %>은 그 안에있는 루비 코드가 무엇이든 반환됩니다. 그 대체 결과는 유효한 자바 스크립트 여야하며, 그렇지 않으면 클라이언트가 처리하려고 시도 할 때 오류가 발생합니다. 그래서 이것이 첫 번째 것입니다 : 유효한 자바 스크립트이 필요합니다.

루비가 생성하는 것은 이중 따옴표가있는 자바 스크립트 문자열 안에 포함되어야합니다. <%= ... %> 주위에는 큰 따옴표가 있어야합니다. 이렇게 생성 된 자바 스크립트는 다음과 같이된다는 것을 의미합니다 :

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

지금의이 <%= ... %> 내부의 루비 부분을 살펴 보자. render(:partial => @review)은 무엇을합니까? 그것은 부분적인 렌더링입니다. 즉, 어떤 종류의 코드 (html, css ... 또는 더 많은 자바 스크립트)를 렌더링 할 수 있다는 것을 의미합니다!

그래서 부분에 간단한 html이 있으면 어떻게 될까요?

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

자바 스크립트가 큰 따옴표로 묶인 문자열을 매개 변수로 사용하고 있다는 것을 기억하십니까? <%= ... %>을 해당 부분 코드로 바꾸면 문제가 발생합니다. href= 바로 뒤에 큰 따옴표가 있습니다!자바 스크립트가 유효하지 않습니다

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

이 발생하지 않도록, 당신의 문자열이 절단되지 않도록 당신이 탈출 이러한 특수 문자를 원하는 -이 대신 생성 뭔가가 필요합니다

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

이것은 무엇입니까 escape_javascript 않습니다. 그것은 반환 된 문자열이 "break"javascript가되지 않도록합니다. 당신이 그것을 사용하면 원하는 출력을 얻을 것이다 :

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

감사합니다!

+4

참으로 아주 좋은 설명 감사합니다. 나는 'escape_javascript'를 사용하는 것이 실제 자바 스크립트를 벗어나기 위해 실제로 사용하지 않기 때문에 오해의 소지가 있다고 생각합니다. 부분에 스크립트 태그를 넣고 원하는 javascript를 실행할 수 있습니다. – Steve

+12

@Steve는 javascript를 깨지 않도록 다른 코드 (예 : html)를 이스케이프 처리하기 때문에 @Steve가 동의합니다. 더 좋은 이름은'escape_for_javascript'입니다. – kikito

+13

'escape_javascript()'는 더 간단한 방법입니다 : 단순한'j()'(적어도 레일즈 4에서는). – mjnissim

7

소스 here을 보면 훨씬 더 명확 해집니다.

이 기능은 다음과 같은 두 가지 수행 :

  1. 그것은 JS_ESCAPE_MAP

    이것의 목적은 확인하는 것입니다

    에 정의 된 것과 에 입력 문자열의 문자를 대체를하는 자바 스크립트 코드 포함 된 외부 문자열 을 방해하지 않고 이 올바르게 serialize됩니다. 예를 들어 자바 스크립트 문자열을 큰 따옴표로 사용하는 경우 코드가 표시되지 않도록하려면 문자열 리터럴의 모든 따옴표를 작은 따옴표로 묶어야합니다.

  2. 이 함수는 결과 문자열이 html로 안전한지 여부도 확인합니다. 그렇지 않은 경우 문자열이 html로 안전하다는 것을 확인하기 위해 필요한 이스케이프 처리를 수행하고 결과를 반환합니다.

escape_javascript를 사용하는 경우 대개 다른 문자열 또는 기존 html 내에 동적으로 포함됩니다. 이 작업을 수행해도 전체 페이지가 렌더링되지 않는지 확인해야합니다.

이 응답의 일부 측면은 다른 응답에서 지적되었지만 모든 항목을 함께 가져와 javascript 이스케이프와 html 이스케이프 간의 차이점을 포함하고자했습니다. 또한 일부 응답은이 함수가 스크립트 삽입을 피하는 데 도움이된다고 말합니다. 나는 그것이 그것이이 기능의 목적이라고 생각하지 않는다. 예를 들어 리뷰에 경고 ('안녕하세요')가있는 경우 노드에 추가하면 팝업이 실행되지 않습니다. 페이지로드시 또는 다른 이벤트를 통해 트리거되는 함수 내에 포함시키지 않습니다. 단지 html의 일부로 경고 ('안녕하세요')가 자바 스크립트로 실행된다는 것을 의미하지는 않습니다.

나는 스크립트 삽입이 불가능하다는 것을 부인할 수 없다고 말했다. 그러나 사용자 데이터를 가져 와서 데이터베이스에 저장할 때 조치를 취해야하는 것을 피하십시오. 제공하는 함수 및 예제는 이미 저장된 정보의 렌더링과 관련이 있습니다.

이 답변을 보내 주시면 감사하겠습니다.

-3

렌더링하는 내용의 javascript를 실행하지 않습니다.

관련 문제