Tuesday, June 22, 2010

使用tapestry5开发http和https自由切换的web application

Tapestry 5提供了一个非常方便的特性,通过使用@Secure 注释,可以让你的页面能够被安全的浏览,也就是说,从其他没有@Secure注释的页面切换到有@Secure的页面(从浏览器角度说,从http切换到 https),几乎不费任何力气。废话少说,看一下用户登入的例子:

开发环境 Windows sp3, firefox 3.6,myeclipse 8.0 (使用eclipse3.4以上也行), JDK 1.6
所需类库 tapestry 5.1.0.5
web服务器 jetty-6.1.3

此例子使用了maven管理depencies, 因此pom.xml应该看起来像这样:

pom.xml dependency代码片段
  1. ……
  2. <dependency>
  3. <groupId>org.apache.tapestry</groupId>
  4. <artifactId>tapestry-ioc</artifactId>
  5. <version>5.1.0.5</version>
  6. <type>jar</type>
  7. <scope>compile</scope>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.apache.tapestry</groupId>
  11. <artifactId>tapestry-core</artifactId>
  12. <version>5.1.0.5</version>
  13. <type>jar</type>
  14. <scope>compile</scope>
  15. </dependency>
  16. ……

实际上此例子只用到了tapestry-core 而已,IOC用于服务注入,有时候配置module的时候需要到tapestry-ioc包,建议两个都导入。

下一步骤,修改WEB-INF下的web.xml,使用tapestry接管http请求:

web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  5. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  6. <context-param>
  7. <param-name>tapestry.app-package</param-name>
  8. <param-value>tapestry5.https</param-value>
  9. </context-param>
  10. <filter>
  11. <filter-name>app</filter-name>
  12. <filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
  13. </filter>
  14. <filter-mapping>
  15. <filter-name>app</filter-name>
  16. <url-pattern>/*</url-pattern>
  17. </filter-mapping>
  18. </web-app>

紧接着创建两个包:

  1. tapestry5.https.pages:用来创建页面类
  2. tapestry5.https.services:配置module或者application等

在包tapestry5.https.pages下创建4个页面,一个是Start.java, Login.java,Welcome.java 和 Error.java, 其中Login.java 必须使用Https连接(使用了@Secure注释),其余的可以通过普通http方式访问;在包tapestry5.https.services下创建AppModule.java用来配置整个应用程序。

tapestry5.https.pages包下的文件:

  1. Start.java 初始页面,使用非安全连接页面
  2. Login.java 用户登入界面,必须使用https连接
  3. Welcome.java 登入成功页面
  4. Error.java 登入失败页面

紧接着在Webroot(web应用程序根目录)下对应tapestry5.https.pages包中的页面,分别创建start.tml,login.tml, welcome.tml和error.tml文件(名称大小写不敏感,但要和tapestry5.https.pages中的java页面文件同名)。看以下截图:

project structure

Start.java,Welcome.java以及Error.java是空类,不包含任何逻辑(用于展示目的),只需编辑对应的start.tml, error.tml以及welcome.tml文件即可:

start.tml
  1. <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" >
  2. <head>
  3. <title> this is a normal page accessed by HTTP</title></head>
  4. <body>
  5. <p>
  6. this is a normal page accessed by HTTP</p>
  7. </body>
  8. </html>

error.tml
  1. <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
  2. <head>
  3. <title> this page should be accessed automatically by HTTPS</title>
  4. </head>
  5. <body>
  6. <p>User name or password error!</p>
  7. </body>
  8. </html>

welcome.tml
  1. <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" >
  2. <head>
  3. <title> this is a normal page accessed by HTTP</title></head>
  4. <body>
  5. <p>
  6. welcome!</p>
  7. </body>
  8. </html>
最后是Login.tml,最重要的一个page:
login.tml
  1. <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
  2. <head>
  3. <title> this page should be accessed automatically by HTTPS</title>
  4. </head>
  5. <body>
  6. <t:form t:id="loginForm">
  7. <t:label t:for="name" />
  8. <t:textfield t:id="name" value="name" />
  9. <t:label t:for="pwd" />
  10. <t:passwordfield t:id="pwd" value="pwd" />
  11. <input type="submit" value="go" />
  12. </t:form>
  13. <t:actionlink t:id="gotostart">return to start</t:actionlink>
  14. </body>
  15. </html>

Login.java主要有两个操作,一个是用户登入,登入成功返回welcome页面,否则返回error页面; 另外一个是点击链接“return to start”返回start页面,由此编辑Login.java如下:

Login.java
  1. package tapestry5.https.pages;
  2. import org.apache.tapestry5.annotations.InjectPage;
  3. import org.apache.tapestry5.annotations.Property;
  4. import org.apache.tapestry5.annotations.Secure;
  5. // here used @Secure annotation,
  6. //therefore this page will be forced to be visited under https
  7. @Secure
  8. public class Login {
  9. @Property
  10. private String name;
  11. @Property
  12. private String pwd;
  13. @InjectPage
  14. private Start start;
  15. @InjectPage
  16. private Welcome welcome;
  17. @InjectPage
  18. private Error error;
  19. Object onSuccess() {
  20. if (name.equals("admin") && pwd.equals("123456")) { return welcome; }
  21. return error;
  22. }
  23. Object onActionFromGotostart() {
  24. return start;
  25. }
  26. }

所有页面编辑完毕,在部署此project到jetty之前,还需要配置整个应用程序,修改tapestry5.https.services下的AppModule.java文件如下:

AppModule.java
  1. package tapestry5.https.services;
  2. import org.apache.tapestry5.SymbolConstants;
  3. import org.apache.tapestry5.ioc.MappedConfiguration;
  4. public class AppModule {
  5. public static void contributeApplicationDefaults(
  6. MappedConfiguration<String, String> configuration) {
  7. // you must enable production mode to access page with @secure annotation under HTTPS mode,
  8. // otherwise it won't work; if you want to switch back to development mode, just set it "false"
  9. configuration.add(SymbolConstants.PRODUCTION_MODE, "true");
  10. // use utf-8 as default encoding
  11. configuration.add(SymbolConstants.CHARSET, "UTF-8");
  12. }
  13. }
最后一步是部署我们的Web程序。为了测试的方便,修改了jetty.xml和jetty-ssl.xml中的端口,即修改端口8080为80, 修改安全端口8443为443,这样测试的的url就从http://localhost:8080//…变成了http://localhost//… 注意端口号没有明确指定,jetty会自动映射的;同时不要忘记启动jetty服务器之前,要添加参数etc/jetty.xml etc/jetty-ssl.xml,否则的话默认只会加载etc/jetty.xml (在etc目录下,jetty自带一个keystore,你可以自己替换成自己的证书,详细请看http://docs.codehaus.org/display/JETTY/How+to+configure+SSL)

部署完项目启动jetty之后,打开浏览器firefox,键入http://localhost/LoginExample/start 会显示如下:

start


然后我们把url中的start改成login,回车:

untrusted!

Opps,由于jetty自带的是一个用于测试https的过期的keystore,因此可以不用理会firefox的安全警告,选择信任此网站即可。

accessLoginHttps_automatically

显然自动进入安全Login页面成功!(当从http页面到此页面时,会自动转入https), 如上所示,此Login页面只能在https下访问,普通http会被自动转入https(本质上是一个http redirect)。

接下来,我们点击return to start返回普通http页面,来验证是否会一直在https模式下浏览普通页面呢?

returnToHttpNormalPage

点击链接,成功返回谱图http页面start!

总结: tapestry5的@Secure注释功能非常强大,隐藏了从http到https,以及https到http切换的繁琐的实现,提高了开发效率。

del.icio.us Tags: ,,