开发用于表单登录处理的 Servlet 过滤器

使用基于表单的登录机制,可以控制登录屏幕的外观。在基于表单的登录中,您指定用于检索用户标识和密码信息的登录页面。您也可以指定当认证失败时显示错误页面。

关于此任务

如果认证前后需要其他认证或其他处理,那么 Servlet 过滤器是一个选择。Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。调用 Servlet 前调用所有附加的 Servlet 过滤器。

任何遵从 Servlet V2.3 规范的 Web 容器都支持基于表单的登录和 Servlet 过滤器。表单登录 Servlet 执行认证,Servlet 过滤器执行附加认证、审计或记录信息。

要使用 Servlet 过滤器执行登录前和登录后操作,为表单登录页面支持或为 /j_security_check URL 配置这些过滤器。j_security_check 由表单登录页面使用包含用户名的 j_username 参数和包含密码的 j_password 参数公布。Servlet 过滤器可以使用用户名参数和密码信息,执行更多认证或其他特殊需要。

过程

  1. Servlet 过滤器实现 javax.servlet.Filter 类。在过滤器类中实现三种方法:
    • init(javax.servlet.FilterConfig cfg)。将 Servlet 过滤器放入服务时,此方法由容器调用一次。传递到此方法的 FilterConfig 包含 Servlet 过滤的初始参数。使用组装工具配置期间,为 Servlet 过滤器指定初始参数。
    • destroy。当 Servlet 过滤器从服务取出时,此方法由容器调用。
    • doFilter(ServletRequest req, ServletResponse res, FilterChain chain)。调用 Servlet 前,容器为映射到此过滤器的每个 Servlet 请求调用此方法。传递给此方法的 FilterChain 链用于调用过滤器链中的下一个过滤器。当链中最后一个过滤器调用 chain.doFilter 方法时,运行原始请求的 Servlet。因此,所有过滤器调用 chain.doFilter 方法,以在过滤后运行原始 Servlet。如果在过滤器代码中实现附加的认证检查,并导致失败,那么不运行原始 Servlet。未调用 chain.doFilter 方法,可以将它重定向到其他一些错误页面。
  2. 如果 Servlet 映射到很多 Servlet 过滤器,以应用程序的 web.xml 部署描述符中列出的顺序调用 Servlet 过滤器。将 Servlet 过滤器类文件放入应用程序的 WEB-INF/classes 目录中。

示例

servlet 过滤的示例。

此登录过滤器可映射到 /j_security_check URL,以执行登录前和登录后操作。

import javax.servlet.*;
     public class LoginFilter implements Filter {
     protected FilterConfig filterConfig;
     // Called once when this filter is instantiated. 
     // If mapped to j_security_check, called 
     // very first time j_security_check is invoked.
     public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        }
     public void destroy() {
        this.filterConfig = null;
        }
      // Called for every request that is mapped to this filter. 
     // If mapped to j_security_check, 
     // called for every  j_security_check action
     public void doFilter(ServletRequest request, 
     ServletResponse response, FilterChain chain) 
         throws java.io.IOException, ServletException   {
         // perform pre-login action here
         chain.doFilter(request, response);  
         // calls the next filter in chain.  
         // j_security_check if this filter is 
         // mapped to j_security_check.
        // perform post-login action here.
                 }
       }
在表单登录期间使用 Servlet 过滤器来执行登录前和登录后处理

此示例说明了在表单登录期间 Servlet 过滤器可执行登录前和登录后处理的一种方法。

Servlet filter source code: LoginFilter.java
/**
 * A servlet filter example: This example filters j_security_check and
 * performs pre-login action to determine if the user trying to log in
 * is in the revoked list. If the user is on the revoked list, an error is
 * sent back to the browser.
 *
 * This filter reads the revoked list file name from the FilterConfig 
 * passed in the init() method. It reads the revoked user list file and
 * creates a revokedUsers list.
 * 
 * When the doFilter method is called, the user logging in is checked 
 * to make sure that the user is not on the revoked Users list.
 *
 */

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class LoginFilter implements Filter {

   protected FilterConfig filterConfig;

   java.util.List revokeList; 
   

   /**
    * init() : init() method called when the filter is instantiated.
    * This filter is instantiated the first time j_security_check is 
    * invoked for the application (When a protected servlet in the 
    * application is accessed).
    */
   public void init(FilterConfig filterConfig) throws ServletException {
      this.filterConfig = filterConfig;

      // read revoked user list
      revokeList = new java.util.ArrayList(); 
      readConfig();
   }


   /**
    * destroy() : destroy() method called when the filter is taken 
    * out of service.
    */
   public void destroy() {
      this.filterConfig = null;
      revokeList = null;
   }

   /**
    * doFilter() : doFilter() method called before the servlet to 
    * which this filter is mapped is invoked. Since this filter is  
    * mapped to j_security_check,this method is called before 
    * j_security_check action is posted.
    */
   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws java.io.IOException, ServletException {


      HttpServletRequest req = (HttpServletRequest)request;
      HttpServletResponse res = (HttpServletResponse)response;

      // pre login action
      
      // get username 
      String username = req.getParameter("j_username");

      // if user is in revoked list send error
      if ( revokeList.contains(username) ) {
      res.sendError(javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED);
      return;
      }
      
      // call next filter in the chain : let j_security_check authenticate 
      // user
      chain.doFilter(request, response);

      // post login action

   }

   /**
    * readConfig() : Reads revoked user list file and creates a revoked 
    * user list.
    */
   private void readConfig() {
      if ( filterConfig != null ) {

         // get the revoked user list file and open it.
         BufferedReader in;
         try { 
               String filename = filterConfig.getInitParameter("RevokedUsers");
               in = new BufferedReader( new FileReader(filename));
         } catch ( FileNotFoundException fnfe) {
               return;
         }
	
         // read all the revoked users and add to revokeList. 
         String userName;
         try {
               while ( (userName = in.readLine()) != null ) 
                   revokeList.add(userName);
         } catch (IOException ioe) {
         }

      }
  
   }

   
}
要点: 在前一个代码样本中,以 public void doFilter(ServletRequest request 开头的行已被分为两行,这仅用于说明。public void doFilter(ServletRequest request 行和它之后的行是一个连续行。
以下是 web.xml 文件的示例,它显示已配置并映射至 j_security_check URL 的 LoginFilter 过滤器:
<filter id="Filter_1">
    <filter-name>LoginFilter</filter-name>
	   <filter-class>LoginFilter</filter-class>
	        <description>Performs pre-login and post-login operation</description>
			 <init-param>
			 <param-name>RevokedUsers</param-name>
			 <param-value>c:\WebSphere\AppServer\installedApps\
                            <app-name>\revokedUsers.lst</param-value>
				</init-param>
</filter-id>

<filter-mapping>
	<filter-name>LoginFilter</filter-name>
	    <url-pattern>/j_security_check</url-pattern>
</filter-mapping>
撤销用户列表文件的示例:
user1
cn=user1,o=ibm,c=us
user99
cn=user99,o=ibm,c=us

指示主题类型的图标 任务主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tsec_servlet
文件名:tsec_servlet.html