Bean 和 Object 转换器
两个没有默认打开的转换器是Bean 和 Object 转换器。Bean转换器可以把POJO转换成Javascript的接合数组(类似与Java中的Map),或者反向转换。这个转换器默认情况下是没打开的,因为DWR要获得你的允许才能动你的代码。
Object转换器很相似,不同的是它直接应用于对象的成员,而不是通过getter和setter方法。下面的例子都是可以用object来替换bean的来直接访问对象成员。
如果你有一个在 <create ...> 中声明的远程调用Bean。它有个一参数也是一个bean,并且这个bean有一个setter存在一些安全隐患,那么攻击者就可能利用这一点。
你可以为某一个单独的类打开转换器:
<convert converter="bean" match="your.full.package.BeanName"/>
如果要允许转换一个包或者子包下面的所有类,可以这样写:
<convert converter="bean" match="your.full.package.*"/>
显而易见,这样写是允许转换所有的JavaBean:
<convert converter="bean" match="*"/>
BeanConverter 和 JavaBeans 规范
用于被BeanConverter转换的Bean必须符合JavaBeans的规范,因为转换器用的是Introspection,而不是Reflection。这就是说属性要符合一下条件:有getter和setter,setter有一个参数,并且这个参数的类型是getter的返回类型。setter应该返回void,getter应该没有任何参数。setter没有重载。以上这些属于常识。如果你用的不是JavaBean,那么你应该用ObjectConverter.
设置Javascript变量
DWR可以把Javascript对象(又名maps,或联合数组)转换成JavaBean或者Java对象。
一个简单的例子可以帮助你。假设你有下面的Java代码:
public class Remoted {
public void setPerson(Person p) {
// ...
}
}
public class Person {
public void setName(String name) { ... }
public void setAge(int age) { ... }
// ...
}
如果这个Remoted已经被配置成Creator了,Persion类也定义了BeanConverter,那么你可以通过下面的方式调用Java代码:
var p = { name:"Fred", age:21 };
Remoted.setPerson(p);
限制属性转换
就像你可以在creator的定义中剔出一些方法一样,converter也有类似的定义。
限制属性转换仅仅对于Bean有意义,很明显原生类型是不要需要这个功能的,所以只有BeanConverter及其子类型(HibernateBeanConverter))有这个功能。
语法是这样的:
<convert converter="bean" match="com.example.Fred">
<param name="exclude" value="property1, property2"/>
</convert>
这就保证了DWR不会调用 fred.getProperty1() 和fred.getProperty2两个方法。另外如果你喜欢"白名单"而不是"黑名单"的话:
<convert converter="bean" match="com.example.Fred">
<param name="include" value="property1, property2"/>
</convert>
安全上比较好的设计是使用"白名单"而不是"黑名单"。
对象的私有成员
通过'object'转换器的参数的一个名为force的参数,可以让DWR通过反射来访问对象私有成员。
语法是这样的:
<convert converter="object" match="com.example.Fred">
<param name="force" value="true"/>
</convert>
直到DWR1.1.3,这里有一个bug,public的field反而不能被发现,所以你需要在public成员上设置force=true。