《TOMCAT权威指南》摘抄
1.对每条ab请求,可以采用下列步骤得到基准调校的结果:
1.配置并重启被测试的Apache httpd和/或Tomcat实例。
2.确信服务器日志没有启动错误。如果有,请按照前面描述的步骤修正错误。
3.在服务器重启后,运行ab命令请求,让服务器服务于首次请求。
4.作为基准调校的一部分,再次运行ab命令行。
5.在所有的请求都完成时,确信ab报告了零错误及non-2xx零响应。
6.在ab请求之间等待几秒钟,从而服务器能返回空闲状态。
7.注意在ab统计信息中每秒的请求数。
8.如果每秒的请求数发生了明显变化,请返回到第4步;否则,每秒的反复请求数就是基准调校的结果。如果该数字经过ab的10次反复请求仍继续发生明显变化,则放弃,记录最后的每秒请求数,作为基准调校的结果。
2.预编译的jsps.xml Ant构建文件
3.记住虽然Tomcat是开源的,但它也是一个非常复杂的应用程序,因此在开始修改源码之前,一定要小心谨慎。如果决定要投入Tomcat源码开发,请使用Tomcat的邮件列表以分享您的想法,并与社区互动。
4.使用APR连接器,而不使用JIO或NIO的连接器,原因有以下几点:
1.HTTPS使用APR连接器可能会更快,因为APR连接器是叫做OpenSSL库文件的本地代码。而JIO和NIO连接器是纯粹的Java代码,并使用了纯粹的Java TLS/SSL编码,大家都知道,比OpenSSL要慢一些。但是,如果没有使用HTTPS,则不用关心这一点。
2.对于某些代码场合(主要是AJP),APR可能会更高效。对这种配置,具有最大吞吐量是比较重要的。
3.由于使用的sendfile(2)系统呼叫,所以APR被设计为处理大型静态文本文件(如提供媒体文件)时更高效。
4.任何连接器实现的所有底层网络编码都是固有的(native)(如JVM是在C/C++中编写的),因此,无论您是否更喜欢APR,取决于您是喜欢来自ASF还是JVM提供商提供的本地网络编码(native network code)。
5.APR一个被广泛接受的用于Web服务器的I/O实现,用C编程语言编写(供Apache httpd使用),而且工作正常。
6.在MS-Windows上,NIO连接器并没有真正起作用,因为NIO似乎在Windows上无法正常发挥作用,至少在使用Sun的Java VM时是这样。在其他操作系统上,这不成为问题。
7.APR使用了便携的、安全随机数产生器,从而Tomcat会话ID在Windows上默认是安全的。
8.APR还有一些其他功能是非常有用的,而核心Java平台并没有提供这些功能。关键是APR是不同于Java的实现,而且包含一组不同的功能。这些新功能可能会放在任何新版的APR中,而且可以修改APR连接器以充分利用这些功能。
5.如果想显示配置一个Connector以使用APR,则可按如下方式设置协议属性:
6.若要让Apache httpd保护WEB-INF及META-INF目录,请在httpd.conf中追加下列内容:
AllowOverride Nonedeny from all
AllowOverride Nonedeny from all
把所有Web应用程中对.htaccess的请求都映射给叫做forbidden.jsp的JSP文件:
htaccess /forbidden.jsp
htaccess *.htaccess
7.一个简单的HttpServlet,它会在文件系统上创建一个文件,并输出文件成功写入的消息。
package com.oreilly.tomcat.servlets;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOTxception;
import java.io.PrintWriter;import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;/*** 该servlet尝试在Web应用程序的文档中写入文档根目录*/
public class WriteFileServlet extends GenericServlet {public void service(ServletRequest request, ServletResponse response)throws IOException, ServletException{//尝试打开一个文件并写入。String catalinaHome = "/opt/tomcat";File testFile = new File(catalinaHome + "/webapps/ROOT", "test.txt");FileOutputStream fileOutputStream = new FileOutputStream(testFile);fileOutputStream.write(new String("testing...\n").getBytes());fileOutputStream.close();//如果执行到此,表示文件已成功地创建了。PrintWriter out = response.getWriter();out.println("File created successfully!");}
}
为了便于在ROOT Web应用程序中编译、安装及测试,编写了下面这个servlet:
# mkdir $CATALINA_HOME/webapps/ROOT/WEB-INF/classes
# export CATALINA_HOME=/opt/tomcat# javac -classpath $CATALINA_HOME/lib/servlet-api.jar -d $CATALINA_HOME/webapps/ROOT/WEB-INF/classes WriteFileServlet.java
然后, 在ROOT Web应用程序的WEB-INF/web.xml部署描述符中加入servlet和servlet-mapping元素:

现在启用SecurityManager并重新启动Tomcat.
然后,访问URL http://localhost:8080/writefile。
8.编写tc-chroot init脚本,以便使用jbchroot而非chroot的绝对路径,并给jbchroot传入一个或多个开关参数来更改用户组和/或组:
#!/bin/sh
#
# chrooted Apache Tomcat servlet容器的linux init脚本。
#
# chkconfig: 2345 96 14
# 说明: Apache Tomcat servlet容器
# 进程名: tc-chroot
# config: /opt/chroot/tomcat/conf/tomcat-env.sh
#APP_ENV="/opt/tomcat/conf/tomcat-env.sh"# 如果存在,则寻找app config文件的源文件。
[ -r "$APP_ENV" ] && . "${APP_ENV}"# 对应于Tomcat 启动/停止 脚本的路径。
TOMCAT_SCRIPT=$CATALINA_HOME/bin/catalina.sh# 程序名
PROG="$0"# 解决 links - $0 可以是一个软链接。
while [ -h "$PROG" ]; dols=`ls -ld "$PROG"`link=`expr "$ls" : `.*-> \(.*\)$'`if expr "$link" : '.*/.*' > /dev/null; thenPROG="$link"elsePROG=`dirname "$PROG"`/"$link"fi
donePROG="`basename $PROG`"
case "$1" instart)echo -n "Starting $PROG: "# Mount /proc.mkdir -p /opt/chroot/procmount -t proc proc /opt/chroot/proc &>/dev/null/usr/local/bin/jbchroot -U tomcat -- /opt/chroot \/bin/bash -c "set -a; . $APP_ENV; \$TOMCAT_SCRIPT start" &>/dev/nulllet RETVAL=$?if [ $RETVAL -eq 0 ]; thenecho "[ OK ]"elseecho "[ FAILED ]"fi;;stop)echo -n "Stopping $PROG: "/usr/local/bin/jbchroot -U tomcat -- /opt/chroot \/bin/bash -c "set -a; . $APP_ENV; \$TOMCAT_SCRIPT stop" &>/dev/nulllet RETVAL=$?if [ $RETVAL -eq 0 ]; then# Give Tomcat some time to perperly stop all webapps.sleep 3# Unmount /proc.umount /opt/chroot/proc &>/dev/nullecho "[ OK ]"elseecho "[ FAILED ]"fi;;*)echo "Usage: tc-chroot {start|stop}"exit 1
esac
9.存在SQL注入的一段代码:
//已经连接到数据库了,创建使用的Statement
Statement statement = connection.createStatement();//创建用于用户登陆的包含SQL查询的常规字符串
// inserting the username and password into the String.
String queryString = "select * from USER_TABLE where USERNAME='" + username + "' and PASSWORD='" + password + "';";// 用计划好的字符串执行该SQL查询
ResultSet resultSet = statement.executeQuery(queryString);// 从数据库中返回结果行,表明用户已登录。
10.BadInputValve属性
className 此Valve实现的Java类名,必须设为com.oreilly.tomcat.valves.BadInputValve
escapeQuotes 在执行请求之前、决定此Valuve是否要转义请求参数中的任何引号(包括双引、单引号和反引号)。默认值为false
escapeAngleBrackets 在执行请求之前,决定此Valves是否要转移参数中的任何尖括号。默认值为false
escapeJavaScript 决定此Valve是否要转义请求参数中任何潜在威胁JavaScript函数与对象的引用。默认值为true
allow 以逗号分隔的一组常规表达式,使该Valve允许处理一个请求。可以不设定,表示指定none。如果没有设置allow而设置了一个或多个deny,则不允许处理请求
deny 以逗号分隔的一组常规表达式,使该Valve拒绝请求。如果在deny清单中,有一个常规表达式与参数名或值的一部分相匹配,则决绝请求。如果没有设定deny且没有设定allow,则表示允许所有请求并过滤其参数。如果没有设定deny,但设置了一个或多个allow,则只有一个或多个allow模式与参数名或值的一部分匹配时,该Valve才允许处理请求。
11.以下是请求所需并安装商业服务器X.509认证的简要步骤:
1.产生服务器端的密钥对,并存储在一个密钥库中;
2.根据密钥对产生认证签名请求(sertificate signing request, CSR).
3.要想从谁那里购买商业服务器授权证书(CA),就把CSR发送给他。
4.接收返回的CA认证及新签名的认证;
5.把该CA认证导入到所安装的Java的cacerts密钥库中。这将允许JVM把您的CA认证辨认为证书授权认证。
6.把签名服务器证书导入到已存储服务器密钥对的相同密钥库中。
12.$CATALINA_HOME/conf目录中的主要配置文件:
server.xml Tomcat主配置文件
web.xml servlet与其他适用于整个Web应用程序设置的配置文件,必须符合servlet规范的标准格式。
tomcat-users.xml Tomcat的UserDatabaseRealm用于认证的默认角色、用户以及密码清单。
catalina.policy Tomcat的Java安全防护策略文件。
context.xml 默认的context设置,应用于安装了Tomcat的所有主机的所有部署内容。
13.filter过滤器允许您用几个程序建立管道。过滤器可以在待定的URL模式交给目标的servlet之前,以及在执行servlet之后,用一段程序来处理这些URL模式。Filter元素有几个子元素:
| 元素 | 必要性 | 含义 |
| icon | 可选的 | 用于在GUI工具中显示 |
| filter-name | 必要的 | 用于filter-mapping的名称 |
| display-name | 可选的 | 用于在GUI工具中显示 |
| description | 可选的 | 用于在GUI工具中显示 |
| filter-class | 必要的 | 过滤器的完整Java类名 |
| init-param | 0或更多 | 此特定过滤器的初始化参数 |
14.servlet元素可以让您给servlet或JSP分配名称,以便用于servlet-mapping及指向一个servlet的其他元素中。
子元素:
| 子元素名 | 可允许的质量 | 含义 |
| icon | 可选择 | 显示图形的图标 |
| servlet-name | 必要 | 名称,如前所述 |
| display-name | 可选择 | 表达GUI工具中的显示名称与描述信息 |
| description | 可选择 | servlet的描述 |
| servlet-class后jsp-file | 必要 | 一个被命名与描述的servlet或JSP名称 |
| init-param | 0个或多个 | servlet专属的初始化参数 |
| load-on-startup | 可选择 | 当启动Tomcat时加载servlet的顺序 |
| run-as | 可选择 | 用来执行此servlet的用户角色名称 |
| security-role-ref | 0个或多个 | 安全防护的角色(相关细节请参阅第2章) |
在Tomcat中,用来编译及执行所有Jsp的JspServlet,其url-pattern元素为:
jsp *.jsp
15.捕捉给定Context(已改变URI)的任何请求,并将这些请求映射到JSP(以输出更新后的URI):
Redirector /redirector.jsp 1 Redirector /*
16.session-config
30
17.如果想将符合*.foo的文件名映射到MIME类型的application/x-ian-test-file,则可以通过追加下列mime-mapping元素:
foo application/x-ian-test-file
18.jdchroot.c源码:
/** jdchroot.c* Linux 和 Solaris 上OpenBSD的chroot命令,由Jason Brittain提供
*/
#ifndef lint
static const char copyright[] ="@(#) Copyright (c) 1988, 1993\n\The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */#ifndef lint
#if 0
static const char sccsid[] = "@(#)chroot.c 8.1(Berkeley) 6/9/93";
#else
static const char rcsid[] = "$OpenBSD: chroot.c,v 1.7 2002/10/29 23:12:06 millert Exp $";
#endif
#endif /* not lint */#include
#include
#include
#include
#include
#include
#include
#include
#include int main(int, char **);
void usage(char *);
static char *getToken(char **, const char *);
int main(int argc, char **argv)
{struct group *gp;struct passwd *pw;const char *shell;char *fulluser, *user, *group, *grouplist, *endp, *p;gid_t gid, gidlist[NGROUPS_MAX];uid_t uid;int ch, gids;unsigned long ul;char *myname;myname = argv[0];gid = 0;uid = 0;gids = 0;user = fulluser = group = grouplist = NULL;while ((ch = getopt(argc, argv, "G:g:U:u:")) != -1) {switch(ch) {case 'U':fulluser = optarg;if (*fulluser == '\0')usage(myname);break;case 'u':user = optarg;if (*user == '\0')usage(myname);break;case 'g':group = optarg;if (*group == '\0')usage(myname);break;case 'G':grouplist = optarg;if (*grouplist == '\0')usage(myname);break;case '?':default:usage(myname);}}argc -= optind;argv += optind;if (argc < 1) usage(myname);if (fulluser && (user || group || grouplist)) {fprintf(stderr, "%s: The -U option may not be specified with any other option\n",myname);exit(-1);}if (group != NULL) {if ((gp = getgrnam(group)) != NULL)gid = gp->gr_gid;else if (isdigit((unsigned char)*group)) {errno = 0;ul = strtoul(group, &endp, 10);if (*endp != '\0' || (ul == ULONG_MAX && errno == ERANGE)) {fprintf(stderr, "%s: Invalid group ID `$s'\n", myname, group);exit(-1);}gid = (gid_t)ul;} else {fprintf(stderr, "%s: No such group `%s'\n", myname, group);exit(-1);}if (grouplist != NULL) gidlist[gids++] = gid;if (setgid(gid) != 0) {fprintf(stderr, "%s: setgid", myname);exit(-1);}}while ((p = getToken(&grouplist, ",")) != NULL && gids < NGROUPS_MAX) {if (*p == '\0')continue;if ((gp = getgrnam(p)) != NULL) gidlist[gids] = gp->gr_gid;else if (isdigit((unsigned char)*p)) {errno = 0;ul = strtoul(p, &endp, 10);if (*endp != '\0' || (ul == ULONG_MAX && errno == ERANGE)) {fprintf(stderr, "%s: INvalid group ID `%s'\n", myname, p);exit(-1);}gidlist[gids] = (gid_t)ul;}else {fprintf(stderr, "%s: No such group `%s'\n", myname, p);exit(-1);}/** 如果指定,则忽视主群组,笔者在上面已经追加了一个主群组.*/if (group == NULL || gidlist[gids] != gid)gids++;}if (p != NULL && gids == NGROUPS_MAX) {fprintf(stderr, "%s: Too many supplementary groups provided\n", myname);exit(-1);}if (gids && setgroups(gids, gidlist) != 0){fprintf(stderr, "%s: setgroups", myname);exit(-1);}if (user != NULL) {if ((pw = getpwnam(user)) != NULL)uid = pw->pw_uid;else if (isdigit((unsigned char)*user)) {errno = 0;ul = strtoul(user, &endp, 10);if (*endp != '\0' || (ul = ULONG_MAX && errno == ERANGE)) {fprintf(stderr, "%s: Invalid user ID `%s'\n", myname, user);exit(-1);}uid = (uid_t)ul;}else {fprintf(stderr, "%s: No such user `%s'\n", myname, user);exit(-1);}}if (fulluser != NULL) {if ((pw = getpwnam(fulluser)) == NULL) {fprintf(stderr, "%s: No such user `%s'\n", myname, fulluser);exit(-1);}uid = pw->pw_uid;gid = pw->pw_gid;if (setgid(gid) != 0) {fprintf(stderr, "%s: setgid\n", myname);exit(-1);}if (initgroups(fulluser, gid) == -1) {fprintf(stderr, "%s: initgroups\n", myname);exit(-1);}}if (chroot(argv[0]) != 0 || chdir("/") != 0) {fprintf(stderr, "%s: %s\n", myname, argv[0]);exit(-1);}if ((user || fulluser) && setuid(uid) != 0) {fprintf(stderr, "%s: setuid\n", myname);exit(-1);}if (argv[1]) {execvp(argv[1], &argv[1]);fprintf(stderr, "%s: %s\n", myname, argv[1]);exit(-1);}if ((shell = getenv("SHELL")) == NULL) shell = "/bin/sh";execlp(shell, shell, "-i", (char *)NULL);fprintf(stderr, "%s, %s\n", myname, shell);/* 没有走样 */
}void usage(char *myname)
{(void)fprintf(stderr, "usage: %s [-g group] [-G group,group,...] ""[-u user] [-U user] newroot [command]\n", myname);exit(1);
}/* 这是Solaris上丢失的strsep的替代品. */
static char *getToken(char **str, const char *delims)
{char *token;if (*str == NULL) {/* No more tokens */return NULL;}token = *str;while (**str != '\0') {if (strchr(delims, **str) != NULL) {**str = '\0';(*str)++;return token;}(*str)++;}/* There is no other token */*str = NULL;return token;
}
19.BadInputValve.java
package com.oreilly.tomcat.valve;import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.ParameterMap;
import org.apache.catalina.valves.RequestFilterValve;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;/*** 过滤恶意用户从HTT请求产生的输入,* 避免遭受包括Cross Site Scripting(XSS)、SQL注入、* 和HTML注入漏洞及其他黑客攻击。
*/
public class BadInputValve extends RequestFilterValve {// -----------------------------------------静态变量/*** 记录日志的Log实例。*/private static Log log = LogFactory.getLog(BadInputValve.class);/*** 关于这一实现的描述信息*/protected static String info ="com.oreilly.tomcat.valve.BadInputValve/2.0";/*** 空字符串数组,重用为toArray()的类型指示器。*/private static final String[] STRING_ARRAY = new String[0];// -----------------------------------------实例变量/*** 该标志判断转义引号(escape quotes)是否为请求的一部分。*/protected boolean escapeQuotes = false;/*** 该标志判断转义尖括号(escape angle brackets)是否为请求的一部分。*/protected boolean escapeAngleBrackets = false;/*** 该标志判断转义JavaScript (escape JavaScript)函数和对象名是否为请求的一部分.*/protected boolean escapeJavaScript = false;/*** 替代映射 (映射、替代的常规表达式)。* 用于替代单引号(') 和双引号(")的转义等同物。* 使其无法用于恶意目的。*/protected HashMap quotesHashMap =new HashMap();/*** 替代映射(映射、替代的常规表达式)。* 用于替代尖括号(<>)的转义等同物。使其无法用于恶意目的。*/protected HashMap angleBracketsHashMap = new HashMap();/*** 替代映射( 映射、替代的常规表达式)。* 用于替代存在安全隐患的JavaScript函数调用转义等同物。* 使其无法用于恶意目的。*/protected HashMap javaScriptHashMap = new HashMap();/*** 用于过滤参数的常规表达式映射。* 如果找到了检索的字符串,则关键在于检查的常规表达式字符串,* 及用于修改参数的常规表达式字符串。*/protected HashMap parameterEscapes =new HashMap();// ------------------------------构造器/*** 构建这个类的新实例,包括默认属性值。*/public BadInputValve() {super();//输出regex转义映射。quotesHashMap.put("\"", """);quotesHashMap.put("\'", "'");quotesHashMap.put("`", "`");angleBracketsHashMap.put("<", "<");angleBracketsHashMap.put(">", ">");javaScriptHashMap.put("document(.*)\\.(.*)cookie", "document.cookie");javaScriptHashMap.put("eval(\\s*)\\(", "eval(");javaScriptHashMap.put("setTimeout(\\s*)\\(", "setTimeout$1(");javaScriptHashMap.put("setInterval(\\s*)\\(", "setInterval$1(");javaScriptHashMap.put("execScript(\\s*)\\(", "execScript$1(");javaScriptHashMap.put("(?i)javascript(?-i):", "javascript:");log.info("BadInputValve instantiated.");}// --------------------------------------------属性/*** 在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求一部分的引号(双引号和单引号)。*/public boolean getEscapeQuotes() {return escapeQuotes;}/*** 在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求一部分的引号(双引号和单引号)。*//** @param escapeQuotes*/public void setEscapeQuotes(boolean escapeQuotes) {this.escapeQuotes = escapeQuotes;if (escapeQuotes) {//转义所有引号。parameterEscapes.putAll(quotesHashMap);}}/*** 在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求一部分的尖括号(<>)。*/public boolean getEscapeAngleBrackets() {return escapeAngleBrackets;}/***在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求一部分的尖括号(<>)*/public boolean getEscapeAngleBrackets() {return escapeAngleBrackets;}/*** 在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求一部分的尖括号(<>)。* @param escapeAngleBrackets*/public void setEscapeAngleBrackets(boolean escapeAngleBrackets) {this.escapeAngleBrackets = escapeAngleBrackets;if (escapeAngleBrackets) {// 转义所有尖括号.parameterEscapes.putAll(angleBracketsHashMap);}}/*** 在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求一部分*的对JavaScript函数的潜在危险引用。*/public boolean getEscapeJavaScript() {return escapeJavaScript;}/*** 在执行请求之前,获取一个标志,决定该门限(Valve)是否将转义作为请求* 一部分的对JavaScript函数和对象的潜在危险引用。** @param escapeJavaScript*/public void setEscapeJavaScript(boolean escapeJavaScript) {this.escapeJavaScript = escapeJavaScript;if (escapeJavaScript) {// Escape potentially dangerous JavaScript method calls.parameterEscapes.putAll(javaScriptHashMap);}}/*** 返回关于该门限(Valve)实现的描述信息。*/public String getInfo() {return info;}// ------------------------------------公共方法/*** 在恶意用户进入web应用程序之前,消除请求参数。** @param request 要被处理的servlet请求* @param response 要被创建的servlet响应** @excaption IOException 如果发生输入/输出错误* @exception ServletException 如果发生servlet错误*/@Overridepublic void invoke(Request request, Response response) throws IOException, ServletException {//跳过对non-HTTP请求与响应的过滤。if (!(request instanceof HttpServletRequest) ||!(response instanceof HttpServletResponse)) {getNext().invoke(request, response);return;}//基于allow和deny,只让请求通过。if (processAllowAndDenies(request, response)) {//过滤存在安全隐患的JavasScript代码,//从而在Tomcat开始执行请求之前,//清楚了黑客的请求。filterparameters(request);//执行该请求getNext().invoke(request, response);}}/*** 使用(摘要)RequestFilterValve 的泛函性* 以终止在参数名和参数值中包含禁用字符串模式的请求** * @param request 要被处理的servlet请求* @param response 要被创建的servlet响应** @exception IOException 如果发生输入/输出错误* @exception ServletException 如果发生servlet错误** @return false 如果请求禁止,否则为true。*/public boolean processAllowsAndDenies(Request request, Response response)throws IOException, ServletException {ParameterMap paramMap = (ParameterMap) ((HttpServletRequest) request).getParameterMap();//循环参数清单。Iterator y = paramMap.keySet().iterator();while (y.hasNext()) {String name = (String) y.next();String[] values = ((HttpServletRequest)request).getParameterValues(name);//查看名字中是否包含禁止模式。if (!checkAllowsAndDenies(name, response)) {return false;}// 检查该模式的参数值。if (values != null) {for (int i=0; i
** 该方法借鉴了RequestFilterValve.process()的大部分精华,* 只有这一方法拥有boolean返回类型而不用调用* getNext().invoke(request, response).** @param property 要过滤的请求属性。* @param response 要被处理的servlet响应。** @exception IOException 如果发生一个输入/输出错误* @exception ServletException 如果发生一个error错误** @return true 如果仍然允许处理该请求。*/public boolean checkAllowsAndDenies(String property, Response response)throws IOException, ServletException {// 如果既没有deny也没有allow,则处理该请求。if (denies.length == 0 && allows.length == 0) {return true;}// 如果有的话,则检查deny模式。for (int i=0; i 0 && allows.length == 0) {return true;}// 否则,拒绝响应请求。ServletResponse sres = response.getResponse();if (sres instanceof HttpServletResponse) {HttpServletResponse hres = (HttpServletResponse) sres;hres.sendError(HttpServletResponse.SC_FORBIDDEN);}return false;}/*** 对具有安全隐患的内容,如果找到了转义字符,则过滤所有现存的参数。** @param request 包含该参数的请求。*/public void filterParameters(Request request) {ParameterMap paramMap = (ParameterMap) ((HttpServletRequest) request).getParameterMap();// 解除参数映射上的锁,从而可以修改该参数。paramMap.setLocked(false);// 循环每个替代模式。Iterator escapesIterator = parameterEscapes.keySet().iterator();while (escapesIterator.hasNext()) {String patternString = (String) escapesIterator.next();Pattern pattern = Pattern.compile(patternString);// 循环参数列表。@SuppressWarnings("unchecked")String[] paramNames = (String[]) paramMap.keySet().toArray(STRING_ARRAY);for (int i=0; i
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
