-------------------------
汗,无知真可怕,Servlert规范中已经有自动跳转到保护页面(Http -> Https)的方法了:
web.xml (SSL)- ...
- <security-constraint>
-
<display-name>Test Auth</display-name>
-
<web-resource-collection>
-
<web-resource-name>Protected Area</web-resource-name>
-
<url-pattern>/*</url-pattern> <!-- 整站SSL -->
-
<http-method>DELETE</http-method>
-
<http-method>GET</http-method>
-
<http-method>POST</http-method>
-
<http-method>PUT</http-method>
-
</web-resource-collection>
-
<user-data-constraint>
-
<description>SSL required</description>
-
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
-
</user-data-constraint>
-
</security-constraint>
- ...
参考:
CONFIDENTIAL - 要保证服务器和client之间传输的数据不能够被修改,且不能被第三方查看到。
INTEGRAL - 要保证服务器和client之间传输的数据不能够被修改。
NONE - 指示容器必须能够在任一的连接上提供数据。(也即,到底是用HTTP,还是是用HTTPS,由Client端决定)
而前两者在实际应用的时候,一般都是是用HTTPS。
web.xml(Basic 认证 + SSL)- ...
- <security-constraint>
-
<display-name>Test Auth</display-name>
-
<web-resource-collection>
-
<web-resource-name>Protected Area</web-resource-name>
-
<url-pattern>/auth/*</url-pattern>
-
<http-method>DELETE</http-method>
-
<http-method>GET</http-method>
-
<http-method>POST</http-method>
-
<http-method>PUT</http-method>
-
</web-resource-collection>
-
<auth-constraint>
-
<role-name>ADMIN</role-name>
-
<role-name>USER</role-name>
-
</auth-constraint>
-
<user-data-constraint>
-
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
-
</user-data-constraint>
-
</security-constraint>
- ...
补充:哎,可是,写的一个文件下载的例子(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- package me.test;
-
-
import java.net.URI;
-
import java.net.URL;
-
-
public class URLTest {
-
-
public static void main(String[] args) throws Exception {
-
URL u1 = new URL(
-
"ftp://zhang3:123456@192.168.1.1:556/zhang.txt?k1=v1&k2=v2#aa");
-
System.out.println(u1.toString());
-
System.out.println(u1.toExternalForm());
-
System.out.println(u1.toURI());
-
-
URL u2 = new URL(
-
"https",
-
u1.getHost(),
-
8443,
-
u1.getFile());
-
// 以下三行的数据均为:
-
//
-
System.out.println(u2.toString());
-
System.out.println(u2.toExternalForm());
-
System.out.println(u2.toURI());
-
-
System.out.println("----------------");
-
URI i1 = new URI(
-
"ftp://zhang3:123456@192.168.1.1:556/zhang.txt?k1=v1&k2=v2#aa");
-
URI i2 = new URI(
-
"https",
-
i1.getUserInfo(),
-
i1.getHost(),
-
8443,
-
i1.getPath(),
-
i1.getQuery(),
-
i1.getFragment());
-
// 以下两行均输出
-
//
-
System.out.println(i2.toURL());
-
System.out.println(i2.toString());
-
}
-
-
}
以下是偶的Filter:
ForceSSLFilter.java- /*
-
* @(#)ForceSSLFilter.java
-
*
-
* Copyright (c) 2011, Digital Yingtan Construction Committee.
-
*/
-
-
package me.test;
-
-
import java.io.IOException;
-
import java.net.URI;
-
import java.net.URISyntaxException;
-
import java.util.ArrayList;
-
import java.util.List;
-
import java.util.regex.Pattern;
-
-
import javax.servlet.Filter;
-
import javax.servlet.FilterChain;
-
import javax.servlet.FilterConfig;
-
import javax.servlet.ServletException;
-
import javax.servlet.ServletRequest;
-
import javax.servlet.ServletResponse;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
-
import org.apache.commons.lang.StringUtils;
-
-
/**
-
* 对某些路径强制使用SSL的Filter。
-
* 如果请求的URL不是 https,则会使其重定向到相应的https路径上。
-
*
-
* 注意:此Filter目前只能用于无状态的WebService等路径。因为https与http在Tomcat等
-
* Servlet容器中会使用不同的SESSION。
-
*
-
* @author 张亮亮 2011/05/26 新建
-
*/
-
public class ForceSSLFilter implements Filter {
-
-
/** 需要强制使用SSL的路径。 */
-
protected List<String> sslPaths = null;
-
-
/** 不需要强制使用SSL的路径。 */
-
protected List<String> noSslPaths = null;
-
-
/** SSL的端口。 */
-
protected int sslPort = 443;
-
-
/** 是否使用重定向。 */
-
protected boolean usingRedirect = true;
-
-
/**
-
* 获得初始值。
-
*
-
* @param fc 配置信息
-
*/
-
public void init(FilterConfig fc) throws ServletException {
-
-
// 参数:需要强制使用SSL的路径
-
String paths = fc.getInitParameter("sslPaths");
-
sslPaths = new ArrayList<String>();
-
if (StringUtils.isNotBlank(paths)) {
-
for (String regexStr : paths.split(",")) {
-
if (StringUtils.isNotBlank(regexStr)) {
-
sslPaths.add(regexStr.trim());
-
}
-
}
-
}
-
-
// 参数:不需要强制使用SSL的路径
-
paths = fc.getInitParameter("noSslPaths");
-
noSslPaths = new ArrayList<String>();
-
if (StringUtils.isNotBlank(paths)) {
-
for (String regexStr : paths.split(",")) {
-
if (StringUtils.isNotBlank(regexStr)) {
-
noSslPaths.add(regexStr.trim());
-
}
-
}
-
}
-
-
// 参数:SSL的端口
-
String port = fc.getInitParameter("sslPort");
-
if (StringUtils.isNotBlank(port)) {
-
sslPort = Integer.valueOf(port);
-
}
-
-
// 参数:是否使用重定向
-
-
String redirect = fc.getInitParameter("usingRedirect");
-
if (StringUtils.isNotBlank(redirect)) {
-
usingRedirect = Boolean.valueOf(redirect);
-
}
-
}
-
-
/**
-
*
-
*/
-
public void destroy() {
-
-
}
-
-
/**
-
*单点登录主要处理方法。
-
*
-
* @param req 请求
-
* @param resp 响应
-
* @param filterChain 响应链
-
*/
-
public void doFilter(ServletRequest req, ServletResponse resp,
-
FilterChain filterChain) throws IOException, ServletException {
-
HttpServletRequest request = (HttpServletRequest) req;
-
HttpServletResponse response = (HttpServletResponse) resp;
-
-
String servletPath = request.getServletPath();
-
-
// 不需要SSL?
-
boolean needFilter = true;
-
for (String regexStr : noSslPaths) {
-
if (Pattern.matches(regexStr, servletPath)) {
-
needFilter = false;
-
break;
-
}
-
}
-
-
if (needFilter && !request.isSecure()) {
-
-
// 是否需要强制SSL?
-
boolean needRedirect = false;
-
for (String regexStr : sslPaths) {
-
if (Pattern.matches(regexStr, servletPath)) {
-
needRedirect = true;
-
break;
-
-
}
-
}
-
-
// 进行跳转
-
if (needRedirect) {
-
if (usingRedirect) {
-
try {
-
URI reqUri = new URI(request.getRequestURL().toString());
-
URI newUri = new URI("https", reqUri.getUserInfo(),
-
reqUri.getHost(), sslPort, reqUri.getPath(),
-
reqUri.getQuery(), reqUri.getFragment());
-
-
response.sendRedirect(newUri.toString());
-
response.flushBuffer();
-
return;
-
} catch (URISyntaxException e) {
-
throw new RuntimeException("请求的URL格式不正确。", e);
-
}
-
} else {
-
response.sendError(403, "此URL必须使用HTTPS访问。");
-
return;
-
}
-
}
-
}
-
-
filterChain.doFilter(request, response);
-
}
-
}
web.xml中的配置
- ...
- <filter>
-
<filter-name>forceSSLFilter</filter-name>
-
<filter-class>
-
me.test.ForceSSLFilter
-
</filter-class>
-
<init-param>
-
<param-name>sslPaths</param-name>
-
<param-value>/auth/.*</param-value>
-
</init-param>
-
<init-param>
-
<param-name>noSslPaths</param-name>
-
<param-value>/auth/1/.*</param-value>
-
</init-param>
-
<init-param>
-
<param-name>sslPort</param-name>
-
<param-value>8443</param-value>
-
</init-param>
-
<init-param>
-
<param-name>usingRedirect</param-name>
-
<param-value>false</param-value>
-
</init-param>
-
</filter>
- ...
不足:Basic认证优先被Servlet容器处理,所以,会造成以下情况;
1. 用户在使用http访问必须要https访问的路径时,被提示输入用户名,密码
2. 然后,显示错误信息(“403 此URL必须使用HTTPS访问” - 如果 web.xml 中usingRedirect为false
或者 跳转到https的访问路径上,但又被要求重新输入一次密码 )
阅读(1620) | 评论(0) | 转发(0) |