2011-02-21 4 views
13

자바 스크립트에서 "2 * (3 + 4)"와 같은 사용자 입력 산술 표현식을 평가해야하지만 보안상의 이유로 eval을 사용하고 싶지 않습니다.Javascript에서 산술 표현의 안전한 평가

...

나는 번호 또는 사업자가 아닌 모든 문자를 제거 할 수 있지만이 어쨌든 안전 할 것입니다 확실하지 않다 사용자가 등 cos, sqrt, 같은 기능을 사용할 수 있다면 좋을 것이다

산술 표현식 평가를 수행하는 Javascript 라이브러리가 있습니까?

+0

자신을 굴리지 않으면 보안 문제를 해결할 수 있습니까? – James

답변

20

당신은 JavaScript Expression Evaluator을 시도 할 수 있습니다 :

이 라이브러리는 라파엘 그라프의 액션 표현 파서의 수정 된 버전입니다. 자바 스크립트 함수 플로터를 작성할 때, 을 으로 바꾸고 싶습니다. 자바 스크립트의 eval 함수을 사용하는 것이 좋습니다. 자신의 브라우저에 코드 만 실행할 수 있기 때문에 현재 보안 위험은 없습니다. 그러나 수학에 편리하므로 (2^x 대신 Math.pow (2^x) 등) 이 아닙니다.

다음 코드는 그렇게 될 것입니다 :

console.info (Parser.evaluate("2 * (3 + 4)")); //prints 14 
+1

감사! 그게 정확히 내가 뭘 찾고 있었는지, 그리고 내가 뽑을 수있는 "표현 평가"에 대한 모든 가능한 변이에 대해 맹세했다. –

1

정규식을 사용하여 허용 목록 이외의 모든 것을 바꿀 수 있습니다. 하지만 자바 스크립트가 클라이언트에서 실행되기 때문에 (AOL http 서버를 실행하지 않는 한) 입력을 수정할 수있는 사람도 누구나 코드를 수정할 수 있습니다. 따라서 실제로는 그렇지 않습니다. 보다 다소 안전합니다. 이미있다.

+1

평가할 표현식을 입력하는 사용자가이 표현식을 평가하는 사용자와 동일한 지 여부에 따라 다릅니다. – Bruno

9

이미 언급했듯이, 대부분의 내장 콘솔의 꽤 많은 이미 사용 할 수있는 무엇인가 할 수있는 모든 사용자에 손상을 주요 브라우저. 그러나 사용자가 Math 속성/메소드를 사용하도록 제한하려는 경우이를 처리 할 수있는 간단한 정규식을 작성할 수 있습니다. 난 당신이 보안상의 이유로 eval을 사용하지 않았다 실현

function mathEval (exp) { 
    var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\[\]"'!&<>^\\?:])/ig, 
     valid = true; 

    // Detect valid JS identifier names and replace them 
    exp = exp.replace(reg, function ($0) { 
     // If the name is a direct member of Math, allow 
     if (Math.hasOwnProperty($0)) 
      return "Math."+$0; 
     // Otherwise the expression is invalid 
     else 
      valid = false; 
    }); 

    // Don't eval if our replace function flagged as invalid 
    if (!valid) 
     alert("Invalid arithmetic expression"); 
    else 
     try { alert(eval(exp)); } catch (e) { alert("Invalid arithmetic expression"); }; 
} 

하지만의 직접 등록되지 않은 단어를 규칙으로 정규식은 꽤 안전해야한다 : 이런 식으로 뭔가 작업을해야합니다 대입 연산자 (=) 및 이진 연산자를 포함하여 Math 개체 및 대부분의 비 수학 JS 연산자. 더 어려운 방법은 일반 언어가 아니기 때문에 수학 표현식을 구문 분석하기 위해 토크 나이저를 작성하는 것입니다.

내가 쓴, 당신이 할 수 있거나 문제를 느낀다면 코멘트를 남겨두면 내가 해결할 수있는 것을 볼 수있을 것이다.


참고 : 이순신 장쩌민은 또한 Math.PI 같은 것들에 대한 소문자를 허용하는 것이 유용 할 수 in JavaScript chat을 언급했다. 그런 경우, 당신은 대체 기능에 다음 else if 문을 추가 할 수 있습니다

else if (Math.hasOwnProperty($0.toUpperCase()) 
    return "Math."+$0.toUpperCase(); 

ifelse 문 (example) 사이를 추가합니다.

+0

위대한 접근 방식은 비슷한 문제를 해결하는데 도움이되었다. – odiseo

+3

"가장 큰 피해는 모든 사용자가 할 수있다. do는 거의 모든 주요 브라우저에서 기본 제공 콘솔을 사용하여 수행 할 수있는 작업입니다. "잘못된 가정을 기반으로합니다. 문자열은 서버와 URL을 통해 브라우저 외부에서옵니다. 가장 좋은 정책은 함수에 대한 입력이 다른 개발자가 애플리케이션에 추가 할 때 기대하지 않는 장소에서 올 것이라고 가정하여 코드하는 것입니다. 즉,'eval '과 같이 지나치게 강력한 연산자를 사용하지 않는 것을 의미합니다. –

+1

@Mike : 나는 100 % 동의하는 것을 압도한다. 다른 출처의 입력을 평가할 때 말한 내용은 사실이지만 사용자 입력 만 평가할 때의 답입니다. –

3

JavaScript의 평가판을 사용하지 않는 math.js의 고급 표현 파서를 사용할 수 있습니다.

http://mathjs.org

용도 :

var ans = math.eval('2 * (3 + 4)'); 

또는 (변수와 함수 지정을 지원) 분석기를 사용 :

var parser = math.parser(); 
var ans = parser.eval('2 * (3 + 4)'); 
1

는 시도 nerdamer

var result = nerdamer('sqrt(4)+cos(1)-2').evaluate(); 
 
document.getElementById('text').innerHTML = result.text();
<script src="http://nerdamer.com/js/nerdamer.core.js"></script> 
 
<div id="text"></div>
01,