有了给定的信息,这里的问题不可能是 esapi。以下单元测试通过:
@Test
public void testWindowsNewline() {
Encoder instance = ESAPI.encoder();
assertEquals("\\x0D\\x0A", instance.encodeForJavaScript("\r\n"));
}
FWIW,标签库只是 esapi 编码器类的包装器。
看来您正在使用嵌入在 javascript 字符串中的标记库,如果我在团队的代码审查中看到这一点,我会将其标记为缺陷,原因如下:
JSP 编译器在呈现页面时会经历多个步骤。您有 HTML 呈现、数据绑定和 JSTL 绑定,仅举几例。由于此排序是特定于实现的,因此您希望尽量避免像这里那样混合代码。
我怀疑 JSP 编译器"\r\n"
在调用<esapi:encodeForJavaScript></esapi:encodeForJavaScript>
.
这是我过去做过的几件事。我倾向于在 Controller/Service 层转义。这个例子假设了 Spring MVC,并且非常自由。
@Controller
public class FooController {
//This should actually be done in a service class, but this is for demo
private Encoder = ESAPI.encoder();
@Autowired
private DataService dataService;
//logic for handling request
public String returnStringEscapedForJavascriptContext(){
OrderBean myOrder = dataService.getMyOrder();
String unescaped = myOrder.getRateErrorMessage();
String escapedAsJavascriptData = encoder.encodeForJavaScript(unescaped);
return escapedAsJavascriptData ;
}
}
如果您要转换myOrder
为 viewBean 等, 则将适用相同的基本逻辑。
另一种解决方案是将安全的 esapi 转义方法包装为一个抽象类,所有视图 bean 都从该类继承,这样,如果你真的必须在 JSP 中完成这项工作,你可以有这样的东西:
public abstract class SecureBean {
private Encoder encoder = ESAPI.encoder();
public String escapeForJavaScript(String input){
return encoder.escapeForJavaScript(input);
}
}
然后继承:
public class OrderBean extends SecureBean {
String rateErrorMessage; //with getters/setters assumed
}
现在在你的jsp中:
var errReason= '${myOrder.escapeForJavaScript(myOrder.rateErrorMessage())}';
其中有些内容有点冗长,但这里的目标是不要尝试踩踏 JSP 的呈现顺序。您也可以考虑编写一个用于编码/解码的适配器接口,这样您就可以换出编码器实现——esapi 已经失去了 OWASP 旗舰地位,并且在大约 1.5 年内没有进行重大修订。