Javascript의 안전한 eval() 대안

생성하는 동안 발생한 문제Discord Bot Studio 는 사용자가 런타임에 평가할 수 있는 변수를 입력할 수 있게 하는 것이었습니다. Discord Bot Studio는 시각적 프로그래밍 도구이므로 친숙한 변수 구문을 제공하는 것이 중요하다고 느꼈습니다. 이상적으로는 사용자가 다음 표기법을 사용하여 변수를 입력할 수 있고 런타임 시 해당 변수의 값으로 대체되기를 원했습니다.

다음과 같은 객체가 있는 경우를 예로 들 수 있습니다.

variableObject {
    variableName: {
        fieldName: "Austin"
    }
}

사용자는 다음 구문을 사용하여 해당 값 "Austin"을 검색할 수 있어야 합니다.

${variableObject.variableName.fieldName}

Rmember, 이것은 시각적 프로그래밍 도구이므로 입력 문자열에 여러 변수가 있을 수도 있고 전혀 없을 수도 있습니다. 입력은 동적일 수 있으므로 런타임에 평가됩니다.

겉보기에 분명한 해결책은 Javascript의 eval()을 사용하는 것입니다.
함수를 사용하여 런타임에 변수를 평가합니다. DBS는 결국 신뢰할 수 없는 사용자 입력을 받는 봇을 생성하므로 안전하지 않습니다. 들어오는 입력을 정리하는 대신 점(.) 구문이 있는 변수를 평가할 수 있는 다른 솔루션을 선택했습니다.

해결책



먼저 위에서 언급한 ${} 표기법을 찾아 정규식을 사용하여 입력 문자열의 변수를 일치시킵니다.

varRegex = /\${(.*?)}/g;

일치 항목에서 초과 ${}를 잘라내고 결과 문자열을 사용자가 참조할 수 있는 변수가 포함된 객체와 함께 다음 함수에 전달합니다.

// desc = variableObject.variableName.fieldName
/* obj = userVariables {
    variableObject {
        variableName: {
            fieldName: "Austin"
        }
    }
}
*/
function getDescendantProp(obj, desc) {
    var arr = desc.split(".");

    while (arr.length) {
        obj = obj[arr.shift()];
    }
    return obj;
}

여기서 obj는 사용자 입력이 액세스해야 하는 모든 변수를 포함하는 객체입니다. Desc는 잘린 일치 문자열입니다. 위의 예를 계속하면 desc는 variableObject.variableName.fieldName과 같습니다. 문자열은 마침표에 따라 배열로 분할됩니다. variableObject.variableName.fieldName은 다음으로 분할됩니다.
[변수 개체, 변수 이름, 필드 이름]. 그런 다음 이러한 배열 값이 순서대로 이동되고 변수를 포함하는 개체에 액세스하기 위한 키로 사용됩니다. 이 함수는 위의 예제 개체를 사용하여 "Austin"문자열만 반환합니다.

이렇게 하면 사용자가 사용할 수 있는 변수를 제한할 수 있으며 일반 Javascript 구문을 사용하여 해당 변수에 액세스할 수 있습니다. variableObject[variableName]도 지원하려는 경우 확장할 수 있습니다. 이것은 모든 시나리오에서 eval()의 진정한 대안은 아니지만 런타임에 개체에 대한 인덱싱에 적합합니다.

좋은 웹페이지 즐겨찾기