Chinaunix首页 | 论坛 | 博客
  • 博客访问: 533439
  • 博文数量: 135
  • 博客积分: 3568
  • 博客等级: 中校
  • 技术积分: 1942
  • 用 户 组: 普通用户
  • 注册时间: 2006-10-19 17:52
文章分类

全部博文(135)

文章存档

2012年(29)

2011年(41)

2010年(26)

2009年(12)

2008年(9)

2007年(12)

2006年(6)

分类: Java

2011-05-27 09:57:08

-------------------------
汗,无知真可怕,Servlert规范中已经有自动跳转到保护页面(Http -> Https)的方法了:
web.xml (SSL)
  1. ...
  2. <security-constraint>
  3.     <display-name>Test Auth</display-name>
  4.     <web-resource-collection>
  5.       <web-resource-name>Protected Area</web-resource-name>
  6.       <url-pattern>/*</url-pattern> <!-- 整站SSL -->
  7.       <http-method>DELETE</http-method>
  8.       <http-method>GET</http-method>
  9.       <http-method>POST</http-method>
  10.       <http-method>PUT</http-method>
  11.     </web-resource-collection>
  12.     <user-data-constraint>
  13.       <description>SSL required</description>
  14.       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  15.     </user-data-constraint>
  16.   </security-constraint>
  17. ...
参考:
CONFIDENTIAL - 要保证服务器和client之间传输的数据不能够被修改,且不能被第三方查看到。
INTEGRAL     - 要保证服务器和client之间传输的数据不能够被修改。
NONE         - 指示容器必须能够在任一的连接上提供数据。(也即,到底是用HTTP,还是是用HTTPS,由Client端决定)
而前两者在实际应用的时候,一般都是是用HTTPS。


web.xml(Basic 认证 + SSL)
  1. ...
  2. <security-constraint>
  3.     <display-name>Test Auth</display-name>
  4.     <web-resource-collection>
  5.       <web-resource-name>Protected Area</web-resource-name>
  6.       <url-pattern>/auth/*</url-pattern>
  7.       <http-method>DELETE</http-method>
  8.       <http-method>GET</http-method>
  9.       <http-method>POST</http-method>
  10.       <http-method>PUT</http-method>
  11.     </web-resource-collection>
  12.     <auth-constraint>
  13.       <role-name>ADMIN</role-name>
  14.       <role-name>USER</role-name>
  15.     </auth-constraint>
  16.     <user-data-constraint>
  17.       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  18.     </user-data-constraint>
  19.   </security-constraint>
  20. ...

补充:哎,可是,写的一个文件下载的例子(AnyChart是用的一个xml数据文件),使用HTTPS的时候,在IE6下,无法加载该XML文件。然后在IE 6 的地址栏中直接访问该URL,发现:在提示的保存弹出窗口中,点击“打开”是能够看到源代码的,但是点击“保存”却报错。郁闷~~~~~
(昨天在开源中国社区看到一则消息,了~~~,下面的评论,看后,无奈~)
看了两个帖子,先记个地址,之后再验证是否能解决偶的问题吧~
http://soido.org/blog/16
http://lgjmfyx.blog.163.com/blog/static/46955077200901710712331/





回头想想前面的工作真可笑。
--------------------------
在Web工程中,如果使用HTTP Basic认证,或FORM认证,为了安全性,最好使用HTTPS的。
因此我们需要禁止HTTP访问,只能HTTPS访问。

如果大家感兴趣,可以研究下Spring Security(偶也不懂,貌似它能做到HTTPS与HTTP Session共享)。

先了解一下URL和URI在java.net.* 包中的用法和区别。详尽描述请参考Javadoc描述:

URLTest.java
  1. package me.test;

  2. import java.net.URI;
  3. import java.net.URL;

  4. public class URLTest {

  5.     public static void main(String[] args) throws Exception {
  6.         URL u1 = new URL(
  7.                 "ftp://zhang3:123456@192.168.1.1:556/zhang.txt?k1=v1&k2=v2#aa");
  8.         System.out.println(u1.toString());
  9.         System.out.println(u1.toExternalForm());
  10.         System.out.println(u1.toURI());

  11.         URL u2 = new URL(
  12.                 "https",
  13.                 u1.getHost(),
  14.                 8443,
  15.                 u1.getFile());
  16.         // 以下三行的数据均为:
  17.         //
  18.         System.out.println(u2.toString());
  19.         System.out.println(u2.toExternalForm());
  20.         System.out.println(u2.toURI());

  21.         System.out.println("----------------");
  22.         URI i1 = new URI(
  23.                 "ftp://zhang3:123456@192.168.1.1:556/zhang.txt?k1=v1&k2=v2#aa");
  24.         URI i2 = new URI(
  25.                 "https",
  26.                 i1.getUserInfo(),
  27.                 i1.getHost(),
  28.                 8443,
  29.                 i1.getPath(),
  30.                 i1.getQuery(),
  31.                 i1.getFragment());
  32.         // 以下两行均输出
  33.         //
  34.         System.out.println(i2.toURL());
  35.         System.out.println(i2.toString());
  36.     }

  37. }


以下是偶的Filter:
ForceSSLFilter.java
  1. /*
  2.  * @(#)ForceSSLFilter.java
  3.  *
  4.  * Copyright (c) 2011, Digital Yingtan Construction Committee.
  5.  */

  6. package me.test;

  7. import java.io.IOException;
  8. import java.net.URI;
  9. import java.net.URISyntaxException;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.regex.Pattern;

  13. import javax.servlet.Filter;
  14. import javax.servlet.FilterChain;
  15. import javax.servlet.FilterConfig;
  16. import javax.servlet.ServletException;
  17. import javax.servlet.ServletRequest;
  18. import javax.servlet.ServletResponse;
  19. import javax.servlet.http.HttpServletRequest;
  20. import javax.servlet.http.HttpServletResponse;

  21. import org.apache.commons.lang.StringUtils;

  22. /**
  23.  * 对某些路径强制使用SSL的Filter。
  24.  * 如果请求的URL不是 https,则会使其重定向到相应的https路径上。
  25.  *
  26.  * 注意:此Filter目前只能用于无状态的WebService等路径。因为https与http在Tomcat等
  27.  * Servlet容器中会使用不同的SESSION。
  28.  *
  29.  * @author 张亮亮 2011/05/26 新建
  30.  */
  31. public class ForceSSLFilter implements Filter {

  32.     /** 需要强制使用SSL的路径。 */
  33.     protected List<String> sslPaths = null;

  34.     /** 不需要强制使用SSL的路径。 */
  35.     protected List<String> noSslPaths = null;

  36.     /** SSL的端口。 */
  37.     protected int sslPort = 443;

  38.     /** 是否使用重定向。 */
  39.     protected boolean usingRedirect = true;

  40.     /**
  41.      * 获得初始值。
  42.      *
  43.      * @param fc 配置信息
  44.      */
  45.     public void init(FilterConfig fc) throws ServletException {

  46.         // 参数:需要强制使用SSL的路径
  47.         String paths = fc.getInitParameter("sslPaths");
  48.         sslPaths = new ArrayList<String>();
  49.         if (StringUtils.isNotBlank(paths)) {
  50.             for (String regexStr : paths.split(",")) {
  51.                 if (StringUtils.isNotBlank(regexStr)) {
  52.                     sslPaths.add(regexStr.trim());
  53.                 }
  54.             }
  55.         }

  56.         // 参数:不需要强制使用SSL的路径
  57.         paths = fc.getInitParameter("noSslPaths");
  58.         noSslPaths = new ArrayList<String>();
  59.         if (StringUtils.isNotBlank(paths)) {
  60.             for (String regexStr : paths.split(",")) {
  61.                 if (StringUtils.isNotBlank(regexStr)) {
  62.                     noSslPaths.add(regexStr.trim());
  63.                 }
  64.             }
  65.         }

  66.         // 参数:SSL的端口
  67.         String port = fc.getInitParameter("sslPort");
  68.         if (StringUtils.isNotBlank(port)) {
  69.             sslPort = Integer.valueOf(port);
  70.         }

  71.         // 参数:是否使用重定向

  72.         String redirect = fc.getInitParameter("usingRedirect");
  73.         if (StringUtils.isNotBlank(redirect)) {
  74.             usingRedirect = Boolean.valueOf(redirect);
  75.         }
  76.     }

  77.     /**
  78.      *
  79.      */
  80.     public void destroy() {

  81.     }

  82.     /**
  83.      *单点登录主要处理方法。
  84.      *
  85.      * @param req 请求
  86.      * @param resp 响应
  87.      * @param filterChain 响应链
  88.      */
  89.     public void doFilter(ServletRequest req, ServletResponse resp,
  90.             FilterChain filterChain) throws IOException, ServletException {
  91.         HttpServletRequest request = (HttpServletRequest) req;
  92.         HttpServletResponse response = (HttpServletResponse) resp;

  93.         String servletPath = request.getServletPath();

  94.         // 不需要SSL?
  95.         boolean needFilter = true;
  96.         for (String regexStr : noSslPaths) {
  97.             if (Pattern.matches(regexStr, servletPath)) {
  98.                 needFilter = false;
  99.                 break;
  100.             }
  101.         }

  102.         if (needFilter && !request.isSecure()) {

  103.             // 是否需要强制SSL?
  104.             boolean needRedirect = false;
  105.             for (String regexStr : sslPaths) {
  106.                 if (Pattern.matches(regexStr, servletPath)) {
  107.                     needRedirect = true;
  108.                     break;

  109.                 }
  110.             }

  111.             // 进行跳转
  112.             if (needRedirect) {
  113.                 if (usingRedirect) {
  114.                     try {
  115.                         URI reqUri = new URI(request.getRequestURL().toString());
  116.                         URI newUri = new URI("https", reqUri.getUserInfo(),
  117.                                 reqUri.getHost(), sslPort, reqUri.getPath(),
  118.                                 reqUri.getQuery(), reqUri.getFragment());
  119.                        
  120.                         response.sendRedirect(newUri.toString());
  121.                         response.flushBuffer();
  122.                         return;
  123.                     } catch (URISyntaxException e) {
  124.                         throw new RuntimeException("请求的URL格式不正确。", e);
  125.                     }
  126.                 } else {
  127.                     response.sendError(403, "此URL必须使用HTTPS访问。");
  128.                     return;
  129.                 }
  130.             }
  131.         }

  132.         filterChain.doFilter(request, response);
  133.     }
  134. }

web.xml中的配置
  1. ...

  2. <filter>
  3.     <filter-name>forceSSLFilter</filter-name>
  4.     <filter-class>
  5.       me.test.ForceSSLFilter
  6.     </filter-class>
  7.     <init-param>
  8.        <param-name>sslPaths</param-name>
  9.        <param-value>/auth/.*</param-value>
  10.     </init-param>
  11.     <init-param>
  12.        <param-name>noSslPaths</param-name>
  13.        <param-value>/auth/1/.*</param-value>
  14.     </init-param>
  15.     <init-param>
  16.        <param-name>sslPort</param-name>
  17.        <param-value>8443</param-value>
  18.     </init-param>
  19.     <init-param>
  20.        <param-name>usingRedirect</param-name>
  21.        <param-value>false</param-value>
  22.     </init-param>
  23.   </filter>

  24. ...

不足:Basic认证优先被Servlet容器处理,所以,会造成以下情况;
1. 用户在使用http访问必须要https访问的路径时,被提示输入用户名,密码
2. 然后,显示错误信息(“403 此URL必须使用HTTPS访问” - 如果 web.xml 中usingRedirect为false
或者 跳转到https的访问路径上,但又被要求重新输入一次密码 )








阅读(1620) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~