DWR中文文档v0.9 09

 

第8章. DWR进阶
8.1 DWR Annotations
DWR标注是用来代替dwr.xml或者与其一同工作的。
8.1.1 初始配置
要使用DWR的标注,你需要在web.xml中配置不同的DWR控制器。

Java代码 复制代码
  1. <servlet>    
  2.    <description>DWR controller servlet</description>    
  3.    <servlet-name>DWR controller servlet</servlet-name>    
  4.    <servlet-class> org.directwebremoting.servlet.DwrServlet             
  5.    </servlet-class>    
  6.    <init-param>    
  7.    <param-name>classes</param-name>    
  8.    <param-value> com.example.RemoteFunctions,    com.example.RemoteBean    
  9.    </param-value>   
  10.    </init-param>    
  11. </servlet>  

 servlet参数classes定义的时可以标注的类的全名,这些名字用逗号分割。
8.1.2 远程访问类
要使一个简单的class可以成为远程访问类,你需要使用@Create和@RemoteMethod标注。

Java代码 复制代码
  1. @Create  
  2.  public class RemoteFunctions {   
  3.     @RemoteMethod  
  4.      public int calculateFoo() { return 42; }    
  5. }  

 没有被@RemoteMethod标注的方法不能被远程访问。 要在Javascript使用不同于类型的名字,使用@Create标注的

name 属性。

Java代码 复制代码
  1. @Create(name = "Functions")    
  2. public class RemoteFunctions {   
  3.   
  4. }  

 8.1.3 对象转换
要使一个简单的bean类可以被远程访问, 使用@Convert和@RemoteProperty标注:

Java代码 复制代码
  1. @Convert    
  2. public class Foo {    
  3.      @RemoteProperty    
  4.      private int foo; public int getFoo() { return foo; }   
  5.     @RemoteProperty    
  6.     public int getBar() { return foo * 42; }    
  7. }  

 要使用复杂的转换器,使用@Convert标注的 converter 属性。


8.2 错误和异常处理


8.2.1 错误处理

在1.0版中错误处理规则有些bug,1.1修复了这些错误。 DWR中有一些全局的处理器(一个错误相关的, 叫做

errorHandler, 另一个警告相关的, 叫做warningHandler)。DWR会默认指定一些全局处理器。你可以这样的改变

全局级别的处理器:

Java代码 复制代码
  1. DWREngine.setErrorHandler(handler);  


你也可以指定单次调用和批量调用的错误和警告处理。例如,在调用元数据中:

Java代码 复制代码
  1. Remote.method(params, {    
  2.    callback:function(data) { ... },    
  3.    errorHandler:function(errorString, exception) { ... }   
  4.  });  

 或者,在批量元数据中:

Java代码 复制代码
  1. DWREngine.beginBatch();   
  2.  Remote.method(params, function(data) { ... });   
  3.   
  4. // 其他的远程调用    
  5. DWREngine.endBatch({    
  6.    errorHandler:function(errorString, exception) { ... }    
  7. });  

 8.2.2 异常
DWR可以转换异常,这样他们会变成Javascript中的错误(他们可以被抛出,因为这可能在异步调用中发生)。 例

如,如果我们远程调用下面的Java类:

Java代码 复制代码
  1. public class Remote {    
  2.     public String getData() { throw new NullPointerException("message"); }    
  3. }  

 那么在Javascript中我们加入下面这些:

Java代码 复制代码
  1. function eh(msg) {    
  2. alert(msg);    
  3. }    
  4. {    
  5. DWREngine.setErrorHandler(eh);   
  6.  Remote.getData(function(data) { alert(data); });  

 结果会通过eh()错误处理器调用alert窗口的,显示消息 – 例如调用异常的getMessage()得到的消息。


8.2.3 找出更多的信息
我们可以把整个异常传地到Javascript中。如果在dwr.xml中加入转换异常本身的能力:

Java代码 复制代码
  1. <convert converter="bean" match="my.special.FunkyException"/>  

 在这里例子中FunkyException被指定,因为它不仅仅包括一个消息,它还包括一些关于异常的额外数据。例如,

SQLException包含错误号,SAX异常包含错误的行和列等等。所以我们可以把上面的例如改为:

Java代码 复制代码
  1. public class Remote {    
  2.      public String getData() {   
  3.          Date when = new Date();   
  4.          throw new FunkyException("message", when);    
  5.          // FunkyException有一个getWhen()方法    
  6.     }   
  7.  }  

 然后在Javascript中是这样的:

Java代码 复制代码
  1. function eh(msg, ex) {    
  2.   alert(msg + ", date=" + ex.when);    
  3. }    
  4. DWREngine.setErrorHandler(eh);    
  5. Remote.getData(function(data) { alert(data); });  

 结果会是一个eh()错误处理器调用的alert框,上面有这些信息:"message, date=Mon Jan 01 2008 10:00:00

GMT+0100" 被传递到错误处理器的ex对象会包含异常在服务端的所有属性,但是异常栈信息没有。


8.3 传递额外的数据到callback函数
通常我们需要传递额外的数据到callback函数,但是因为所有的回调函数都只有一个参数(远程方法的返回结果)

,这就需要一些小技巧了。 解决方案就是使用Javascript的闭包特性。 例如,你的回调函数原本需要像这个样

子:

Java代码 复制代码
  1. function callbackFunc(dataFromServer, dataFromBrowser) {   
  2.     // 用dataFromServer和dataFromBrowser做些事情......    
  3. }  

 那么你可以像这个组织你的函数:

Java代码 复制代码
  1. var dataFromBrowser = ...;    
  2. // 定义一个闭包函数来存储dataFromBrowser的引用,并调用dataFromServer    
  3. var callbackProxy = function(dataFromServer) {    
  4.     callbackFunc(dataFromServer, dataFromBrowser);   
  5.  };    
  6. var callMetaData = { callback:callbackProxy };    
  7.   
  8. Remote.method(params, callMetaData);  

 换句话说,现在你作为callback函数传递过来的不是一个真正的callback,他只是一个做为代理的闭包,用来传

递客户端的数据。 你可以用更简介的形式:

Java代码 复制代码
  1. var dataFromBrowser = ...;    
  2. Remote.method(params, {    
  3.    callback:function(dataFromServer) {    
  4.      callbackFunc(dataFromServer, dataFromBrowser);    
  5.   }   
  6.  });  

 8.4 从其他的URL读取数据
如果你需要读取其他web应用程序生成的页面,并返回到Javascript中。非常简单。只要在你的Java类里面包括下

面这写代码:

Java代码 复制代码
  1. public String getInclude() throws ServletException, IOException{   
  2.  return WebContextFactory.get().forwardToString("/forward.jsp");    
  3. }  

 很明显你应该把"/forward.jsp"替换成你要forward到的页面的URL。这个URL必须以一个斜杠开始,因为它只是调

用 HttpRequest.forward() 。 你可以用这个方法在传递之前任何定制你的页面。
 
8.5 安全
我们很谨慎的对待DWR的安全问题,并且认为有必要解释一下避免错误要做的事情。 首先DWR让你明确哪些是被远

程调用的,是如何被远程调用。原则就是DWR必须调用那些你明确允许的代码。 dwr.xml要求你为每一个远程类定

义一个'create'项。你还可以通过指定include和exclude元素来更精确的控制远程调用Bean中可以被调用的方法

。 除此之外如果你希望允许DWR在转换你的JavaBean到Javascript或者从Javascript转换到JavaBean时有一定的

许可限制,同样可以精确控制哪些Bean的属性可以被转换。 一个很明显但又必须指出的 – 不要在生产环境中打

开test/debug模式控制台。如何打开或关闭debug控制台在配置web.xml部分可以找到详细描述。
审查 - DWR带来的最大好处
很值得对比一下DWR和Servlet、JSP或周围的其他web框架。 如果你要审查基于DWR的功能,那是非常简单的。看

看dwr.xml你就能得到一个哪些方法被暴露到外面的描述了。你也可以俯视全局用DWR可以访问哪些资源。 但是要

在其他系统里做这件事可不是这么容易。如果是Servlet你需要检查WEB-INF/web.xml文件,然后检查写在Servlet

中的request.getParameter(...)。如果是Struts和其他Framework你需要检查配置文件,然后顺着流程检查代码

,看请求信息出了什么问题。
访问控制
DWR允许你通过两种基于J2EE的机制来进行访问控制。首先你可以基于J2EE角色定义DWR的访问。其次你可以在DWR

里面定义访问方法的角色。
 其他方面
DWR不允许你定义任何内部类的create和convert。这样设计是为了不出现意外的攻击来操作DWR的核心文件以提升

访问权限。
风险
有什么机会可以让攻击者窥视你的系统呢?使用DWR你攻击者可以使服务器创建任何你在dwr.xml中指定的Java对

象的实例。并且(如果你用BeanConverter)Java类的任何方法、以及方法任何参数都是可见的。这些类的任何一个

属性都有可能是攻击者需要的。 如果你知道DWR是怎么工作的,这些都是很显而易见的结论,但是往往粗心会造

成问题。如果你创建了一个有appendStringToFile()方法的FileBean的类,而且用DWR把它暴露出去,那么你就给

了攻击者一个机会来填满你的文件系统。
 
你必须时刻注意用了DWR以后,有没有给攻击者什么机会。 一般来说这样的情景让人感觉使用DWR是有风险的,但

是这样的问题在所有的传统web架构中都存在,只是在那些架构中这些不明显,所以就很难被修复。
保证更加安全
这已经很安全了,那么你还能做什么来保证更加安全了?首先记住上面这些关于审查的内容,当web应用的其他地

方不安全时,即使它看上去很安全,过多的关注DWR是很愚蠢的。如果DWR让人感觉恐惧,那是因为它的问题都在

明处。所以第一步是多检查几遍传统架构的问题。 你可以通过把可远程访问的类放到不同的包里,并且使用代理

来防止DWR访问机制出问题。如果你愿意还可以再次检查基于角色的安全控制。这些内容只是在检查DWR已经为你

做的事情。 比多检查几次更好的方法是检查DWR的源码,保证它是在正确的工作。这些代码已经被很多人检查过

了,但多双眼睛总是有好处的。
整合Acegi
DWR可以整合Acegi security framework。更多的信息见整合DWR和Acegi.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值