偶是测试新手,希望前辈们能多多指教。
使用Filter技术防止用户非法访问页面
上一篇 /
下一篇 2009-05-05 13:35:16
/ 个人分类:与WebService相关技术
一 Filter概述
Filter技术是servlet 2.3 新增加的功能,它新增加的功能包括:
1.应用程序生命周期事件控制
2.新的国际化
3.澄清了类的装载规则;
4.新的错误及安全属性;
5.不赞成使用HttpUtils 类
6.各种有用的方法
7.阐明并扩展了几个servletDTD
8.filter功能
其中最重要的就是filter功能。它使用户可以改变一个request和修改一个response,
Filter不是一个servlet,它不能产生一个response它能够在一个request到达servlet之前
预处理request,也可以在离开servlet时处理response。换种说法,filter其实是一个
“servlet chaining”(servlet 链)。
一个filter 包括:
1.在servlet被调用之前截获
2.在servlet被调用之前检查servletrequest
3.根据需要修改request头和request数据
4.根据需要修改response头和response数据
5.在servlet被调用之后截获
二 Filter在检修ABC系统中的应用
检修ABC系统在初期搭建框架的时候决定使用Filter来处理用户非法访问URL以及Session过期等问题。
我们首先定义了一些可以通过URL直接访问的页面,如登陆页面,重登陆页面等。当用户没有登陆而
尝试访问受保护的URL时,Filter将拦截该请求,并把访问的URL重定向到登陆页面。
在web.xml中的配置如下:
<filter>
<filter-name>filterservlet</filter-name>
<filter-class>com.comtop.app.common.FilterServlet</filter-class>
<init-param>
<param-name>freePages</param-name>
<param-value>
/Login.jsp;/LoginAction.do;/index.jsp;/ReLogin.jsp;/SSOLoginAction.do;
</param-value>
</init-param>
<init-param>
<param-name>toPage</param-name>
<param-value>/ReLogin.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterservlet</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filterservlet</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
在<filter></filter>中定义一些基本信息,比如filter的名称,filter的类以及相关初始参数。这里我
们把能直接访问的页面定义为freePages,并定义了它的值。还定义了默认的重定向页面,Relogin.jsp。
接着定义了filter-mapping,让后缀名为.do或.jsp的URL都被Filter所保护。
FilterServlet具体代码(import部分省略):
publicclassFilterServletextendsHttpServletimplementsFilter{
privateFilterConfig filterConfig;
privateString[]freePages;
privateStringtoPage=null;
privatestaticLoggerlogger;
/**
* 初始化filter(这里重写父类的方法)
* @param filterConfig FilterConfig filter配置对象
* @throws ServletException
*/
publicvoidinit(FilterConfig filterConfig)throwsServletException{
logger=Toolkit.getInstance().getLogger(this.getClass().getName());
inti=0;
Stringpages=null;
StringTokenizerstrTokenizer=null;
if(logger.isDebugEnabled()){
logger.debug("init validate session filter ");
}
this.filterConfig=filterConfig;
//以下从配置文件获取配置信息
this.toPage=filterConfig.getInitParameter("toPage");
pages=filterConfig.getInitParameter("freePages");
if(toPage==null||pages==null||toPage.trim().length()==0||
pages.trim().length()==0){
logger.error("web.xml中filterServlet没有配置初始化参数\"toPage\"或\"freePage\".");
thrownewServletException("web.xml中filterServlet没有配置初始化参数
\"toPage\"或\"freePage\".");
}
if(logger.isDebugEnabled()){
logger.debug("toPage:"+toPage);
logger.debug("freePages:"+pages);
}
strTokenizer=newStringTokenizer(pages,";");
this.freePages=newString[strTokenizer.countTokens()];
while(strTokenizer.hasMoreTokens()){
freePages[i++]=strTokenizer.nextToken();
}
if(!isFreePage(toPage)){
logger.error("web.xml中filter初始化参数\"toPage\"的值必须是\"freePage\"中的某个页面.");
thrownewServletException("web.xml中filter初始化参数\"toPage\"的值
必须是\"freePage\"中的某个页面.");
}
}
/**
* 判断一个请求URI是否是不过滤的页面
* @param requestURI String 请求URI
* @return boolean 返回true为不过滤页面
*/
privatebooleanisFreePage(StringrequestURI){
booleanisFree=false;
for(inti=0;i<freePages.length;i++){
if(requestURI.endsWith(freePages[i])){
returntrue;
}
}
returnisFree;
}
/**
* 判断请求是否为有效Session
* @param request ServletRequest 请求对象
* @return boolean 返回true为有效Session
*/
privatebooleanisValidSession(ServletRequestrequest){
HttpServletRequest httpRequest=(HttpServletRequest)request;
if(httpRequest.getSession().getAttribute(GlobalConstants.SECURITY_LOGIN_KEY)
==
GlobalConstants.SECURITY_IS_LOGIN){
returntrue;
}
if(logger.isDebugEnabled()){
logger.debug("Session无效,请求:"+httpRequest.getRequestURI());
}
returnfalse;
}
/**
* 过滤动作
* @param request ServletRequest 请求对象
* @param response ServletResponse 响应对象
* @param filterChain FilterChain 过滤器链对象
*/
publicvoiddoFilter(ServletRequestrequest,ServletResponse response,FilterChain
filterChain){
StringrequestURI=null;
ActionErrors errors=newActionErrors();
ActionError errorSession=null;
HttpServletRequest httpRequest=(HttpServletRequest)request;
HttpServletResponse httpResponse=(HttpServletResponse)response;
requestURI=httpRequest.getRequestURI();
if(logger.isDebugEnabled()){
logger.debug("Session filter RequestURI:"+requestURI);
}
if(!isFreePage(requestURI)){//如果是保护页面
if(!isValidSession(request)){//如果Session无效
StringtoPageURL=null;
try{
toPageURL=httpRequest.getContextPath()+toPage;
httpResponse.encodeRedirectURL(toPageURL);
httpResponse.sendRedirect(toPageURL);//转发响应
}catch(IOExceptionex){
logger.error("Session filter过滤时发生IO异常",ex);
}
}
}
if(!httpResponse.isCommitted()){//如果响应未提交,交给过滤器链
try{
filterChain.doFilter(request,response);
}catch(ServletException sx){
filterConfig.getServletContext().log(sx.getMessage());
}catch(IOExceptioniox){
filterConfig.getServletContext().log(iox.getMessage());
}
}
}
//父类的方法
publicvoiddestroy(){
}
publicFilterConfig getFilterConfig(){
returnthis.filterConfig;
}
publicvoidsetFilterConfig(FilterConfig filterConfig){
this.filterConfig=filterConfig;
}
}
这里isFreePage方法判断用户访问的URL是否是受保护的,从配置文件中将freePages的值得到后,以分号
为隔离符将它们取出放到一个数组中,这个数组存放的每个String都是一个freePage。另外,isValidSession
方法判断在session中是否存在用户的登陆信息,如果用户未登陆,则返回false。每一个filter从doFilter()方法
中得到当前的request及response,在doFilter()方法中,以下代码完成核心判断:
if(!isFreePage(requestURI)){//如果是保护页面
if(!isValidSession(request)){//如果Session无效
StringtoPageURL=null;
try{
toPageURL=httpRequest.getContextPath()+toPage;
httpResponse.encodeRedirectURL(toPageURL);
httpResponse.sendRedirect(toPageURL);//转发响应
}catch(IOExceptionex){
logger.error("Session filter过滤时发生IO异常",ex);
}
}
}
只有是通过isFreePage(requestURI)和isValidSession(request)两层验证的页面才能被访问到,基本实
现了防止用户非法访问页面的情况。在实际项目中还可以添加更多的验证方法。
收藏
举报
TAG: