用SERVLET过滤来实现权限控制
简介
过滤是SERVLET2。3规范新有的功能,目前TOMCAT4,WEBLOGIC7都已支持。它能实现很多以前使用不便或很难实现的功能,在产品体系中,我们可以很好地使用SERVLET过滤,使得各个部件可以在保持系统统一权限控制的前提下,来实现各个独自的个性权限系统。
下面先看下SERVLET过滤是如何工作的,如下图:
图 1. 过滤器与 J2EE 请求处理
由图我们可以看出,SERVLET过滤是在J2EE平台内WEB容器中执行,任何静态或动态业务请求都将通过这个过滤通道。
优点
和传统架构相比,SERVLET过滤的优点如下:
在传统架构中:
每次接受到请求,挂钩式方法就被调用,不论它们是否执行(有时甚至是空的)。
方法的作用域及并发关系(每个方法可能在不同的线程上被调用)不允许在处理相同的请求时简单、高效地共享不同挂钩式方法调用间的变量和信息。
在SERVLET过滤中:
嵌套的方法调用通过一系列过滤器实现,它仅有应用于当前请求的过滤器组成;基于挂钩式调用的传统执行方式需要在处理短句中调用挂钩式例程,即使一个特定短句的处理逻辑不起任何作用。
局部变量在实际的过滤方法返回之前都作保留,并且可用(因为上游过滤器的调用总在堆栈上,等待后续调用的返回)。
过滤的实现
调用链
所有过滤器都服从调用的过滤器链,并通过定义明确的接口得到执行。一个执行过滤器的 Java 类必须执行这一 javax.servlet.Filter 接口。这一接口含有三个过滤器必须执行的方法:
doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。这同样是上游过滤器调用的方法。引入的 FilterChain 对象提供了后续过滤器所要调用的信息。
init(FilterConfig):这是一个容器所调用的初始化方法。它保证了在第一次 doFilter() 调用前由容器调用。您能获取在 web.xml 文件中指定的初始化参数。
destroy():容器在破坏过滤器实例前,doFilter()中的所有活动都被该实例终止后,调用该方法。
嵌套调用在 doFilter() 方法执行中发生。除非您建立一个过滤器明确阻止所有后续处理(通过其它过滤器及资源处理器),否则过滤器一定会在 doFilter 方法中作以下的调用:
FilterChain.doFilter(request, response);
安装过滤器:定义与映射
容器通过 Web 应用程序中的配置描述符 web.xml 文件了解过滤器。有两个新的标记与过滤器相关:<filter> 和 <filter-mapping>。应该指定它们为 web.xml 文件内 <web-app> 标记的子标记。
过滤器定义的元素
<filter> 标记是一个过滤器定义,它必定有一个 <filter- name> 和 <filter-class> 子元素。<filter-name> 子元素给出了一个与过滤器实例相关的、基于文本的名字。<filter-class> 指定了由容器载入的实际类。您能随意地包含一个 <init-param> 子元素为过滤器实例提供初始化参数。例如,下面的过滤器定义指定了一个叫做 IE Filter 的过滤器:
清单 1. 过滤器定义标记
<web-app>
<filter>
<filter-name>IE Filter</filter-name>
<filter-class>com.ibm.devworks.filters.IEFilter</filter-class>
</filter>
</web-app>
容器处理 web.xml 文件时,它通常为找到的每个过滤器定义创建一个过滤器实例。这一实例用来服务所有的可用 URL 请求;因此,以线程安全的方式编写过滤器是最为重要的。
过滤器映射及子元素
<filter-mapping> 标记代表了一个过滤器的映射,指定了过滤器会对其产生作用的 URL 的子集。它必须有一个 <filter-name> 子元素与能找到您希望映射的过滤器的过滤器定义相对应。
我们可以使用 <servlet-name> 或 <url-pattern> 子元素来指定映射。<servlet-name> 指定了一个过滤器应用的 servlet (在 web.xml 文件中的其它地方已定义)。
注意:在这里我们可以使用 <url-pattern> 来指定一个该过滤器应用的 URL 的子集。例如, /* 的样式用来代表该过滤器映射应用于该应用程序用到的每个 URL,/GL/ * 的样式则表明该过滤器映射只应用于总帐专有的 URL,而NT/*则表明过滤器只应用于非税专有的URL。
容器使用这些过滤器映射来确定一个特定的过滤器是否应参与某个特定的请求。清单 1 是为应用程序的所有 URL 定义的应用于 IE Filter 的一个过滤器映射:
清单 2. 过滤器映射标记
<filter-mapping>
<filter-name>GL Filter</filter-name>
<url-pattern>/GL/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NT Filter</filter-name>
<url-pattern>/NT/*</url-pattern>
</filter-mapping>
附
package freeview;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: FreeView Stu.</p>
* @author macken
* @version 1.0
*/
public class NTFilterServlet extends HttpServlet implements Filter {
private FilterConfig filterConfig;
//Handle the passed-in FilterConfig
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
//Process the request/response pair
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException,IOException {
//权限控制代码
}
//Clean up resources
public void destroy() {
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>filterservlet</filter-name>
<filter-class>freeview.FilterServlet</filter-class>
</filter>
<filter-mapping>
<filter-name>filterservlet</filter-name>
<url-pattern>/NT/*</url-pattern> ß--通过此描述说明只对NT部件进香权限控制过滤
</filter-mapping>
<listener>
<listener-class>freeview.ListenerServlet</listener-class>
</listener>
<servlet>
<servlet-name>debugjsp</servlet-name>
<description>Added to compile JSPs with debug info</description>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>classdebuginfo</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>debugjsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
</web-app>