弹簧视图安全

Posted

技术标签:

【中文标题】弹簧视图安全【英文标题】:Spring view safety 【发布时间】:2012-04-24 07:37:30 【问题描述】:

是否可以在 Spring 中定义视图命令的类型?就像现在一样,改变命令类中的任何内容对我们来说都是危险的。视图可能会使用这些类的属性 (path="myDto.persons[0].name"),但如果命令类中的任何内容发生更改,视图只会在运行时失败。

我们 MVC 堆栈的所有其他部分都经过测试,因此我们可以在需要时安全地进行重构。唯一的问题是视图,因为路径“只是字符串”,我们不能以任何合理的方式搜索和替换我们使用特定命令的任何地方。

如果有某种方法可以告诉 Spring 该命令实际是什么类型,那将是一个很大的帮助,因此可以在我们对 .jsp 进行预编译时对其进行验证。编辑视图时还有一个额外的好处是完成,但我想这更像是一个 IDE 问题。

那么,你们中的任何人都知道如何以及是否可能吗?

【问题讨论】:

【参考方案1】:

如果您完全重新设计您的 JSP 文件(如果我自己这么说的话,这是一种非常丑陋的方式),可能会为您的视图添加类型安全。

Servlet 为您提供类型安全,因为那是 Java 代码。如果你重构你的类并且遗漏了一些东西,编译器会立即告诉你你错过了它。但是 JSP 取代了 servlet 作为一种视图技术,提供了更加动态/快速的开发速度(不再有无休止的out.write 指令打开标签、关闭标签、转义引号等)。

正如您所注意到的,EL 表达式基本上是字符串,它们稍后会在运行时被评估并在运行时失败。即使您precompile the JSPs,它仍然会失败,因为 EL 在生成的 servlet 中仍然是字符串。它们要么按原样传递给标签和 evaluate it themselves,要么如果使用 JSP 2.x 版本,则 servlet 容器本身在将表达式作为值传递之前将其包装在评估调用中。

基本上对于低于 JSP 2 的版本,对于像这样的标签:

<my:tag value="$bean.someProp" />

你会得到如下结果:

myTagInstance.setValue("$bean.someProp");

在 servlet 中。

标签本身会在运行时对该字符串进行评估。

对于 JSP 2,你并没有变得更好,评估仍然发生在运行时,但是 servlet 容器从标记中消除了这个负担,生成如下代码:

myTagInstance.setValue((SomePropTypeCastHere) ProprietaryServletContainerEvaluationUtil.evaluate("$bean.someProp"));

如果在评估发生时对象本身的内容不是预期的内容,则会得到奇怪的结果或错误。

在 JSP 中强制执行静态类型的唯一方法(我知道)是将 Java 代码带回 JSP 中(发明 EL 是为了消除这种东西)。这就是为什么我在乞求时说您必须以​​丑陋的方式更改您的 JSP。

If all your tags can use &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt; values, you can use scriptlets to enforce type safety.

这样的标签:

<my:tag value="<%=bean.getSomeProp()%>" />

现在被转换成这个:

myTagInstance.setValue(bean.getSomeProp());

如果someProp 属性被重命名、删除、更改类型或其他什么,编译器可以告诉您相关情况。 IDE本身应该可以告诉你,你甚至不需要precompile the JSPs。

如果我没记错的话,Spring 标签支持运行时表达式,所以这应该可以工作......如果你愿意搞乱你的 JSP,那就是!

至于 IDE 对完成的支持,您对 scriptlet 有支持,但对 EL 没有。那是因为对于 EL,它是相同的讨论,它发生在运行时。 IDE 如何在执行 JSP 时知道上下文中的内容(页面、请求、会话等),以及在开发 JSP 时知道这些内容?

【讨论】:

以上是关于弹簧视图安全的主要内容,如果未能解决你的问题,请参考以下文章

弹簧 websocket 没有弹簧安全

弹簧反应的弹簧安全会话超时

弹簧安全 AntMatcher 不工作

由于弹簧安全性,@Controller 被忽略

如何使弹簧安全允许使用休息服务

有没有办法在没有弹簧安全的情况下使用弹簧过滤器链?