偶是测试新手,希望前辈们能多多指教。

使用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:

 

评分:0

我来说两句

Open Toolbar