參考文章
[http://www.ibm.com/developerworks/cn/java/j-pj2ee10/index.html]
[http://www.programfan.com/article/showarticle.asp?id=1836]
servlet過濾器是小型的web組件,它能夠處理傳入的請求和傳出的響應。Filter 不是一個servlet,它不能產生一個response,它能夠在一個request到達servlet之前預處理request,也可以在離開servlet時處理response。它具有高度的透明性,無需更改應用程序代碼,就可以根據需要添加、修改或從應用程序中將它刪除。
一個filter 包括:
1. 在servlet被調用之前截獲;
2. 在servlet被調用之前檢查servlet request;
3. 根據需要修改request頭和request數據;
4. 根據需要修改response頭和response數據;
5. 在servlet被調用之后截獲.
你能夠配置一個filter 到一個或多個servlet;單個servlet或servlet組能夠被多個filter 使用。幾個實用的filter包括:用戶辨認filter,日志filter,審核filter,加密filter,符號filter,能改變xml內容的XSLT filter等。
一個客戶化的過濾器要實現Filter接口的三個方法:init()、destroy()和doFilter()。
1. init():在容器實例化過濾器時調用,該方法接受一個FilterConfig類型的對象做為輸入。
2. destroy():執行一些清理操作。
3. doFilter():類似servlet的doPost()、doGet()方法,執行具體的過濾任務。
下面給出一個可執行程序范例,它包含main函數,也可以部署到web應用中。
package utils;

import java.io.IOException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import bean.User;
public class UrlFilter implements Filter {

@SuppressWarnings("unused")
private FilterConfig filterConfig;
private FilterChain chain;
private HttpServletRequest request;
private HttpServletResponse response;
public void destroy() {
this.filterConfig = null;
}

public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}

public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
this.chain = chain;
this.request = (HttpServletRequest) servletRequest;
this.response = ((HttpServletResponse) servletResponse);
String url = request.getServletPath();
if (url == null)
url = "";
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (noFileUrl(url, request)) { //不需要判斷權限的請求如登錄頁面,則跳過
chain.doFilter(request, response);
} else if (user == null) {
String action = request.getParameter("action");
if (!"login".equals(action)) {
response.sendRedirect("/zmdsl/admin/index.jsp");//返回登錄頁面
}
} else {
verifyUrl(url, user);//判斷當前user是否擁有訪問此url的權限
}
}
/**
*
* @param url 當前請求的url
* @param user 當前登錄用戶
* @throws IOException
* @throws ServletException
*/
private void verifyUrl(String url, User user)throws IOException, ServletException {
// 獲取user擁有的所有資源串
Set<String> royurl = new HashSet<String>();
royurl.add("/newsAction.do?action=adminQueryPage&typeId=3");//為用戶分配訪問此地址的權限。在真正項目中,此Set集合可能要
//通過查詢數據庫user、role、menu等表,來獲取當前用戶所擁有的全部可訪問資源
if (royurl != null && royurl.size() > 0
&& pass(royurl, url, request.getParameterMap())){
chain.doFilter(request, response);
} else {
response.setContentType("text/html;charset=GBK");
response
.getWriter()
.println(
"<div style='margin: 100 auto;text-align: center;"
+ "font: bold 18px 宋體;color: #0066CC;vertical-align: middle'> Sorry,您沒有權限訪問該資源!</div>");
}
}

/**
* 是否需要判斷權限,如客戶端瀏覽、登錄頁面則不需要判斷權限
*/

protected boolean noFileUrl(String url, HttpServletRequest request) {
if (url.indexOf("/index.jsp") >= 0 || url.indexOf("login") > 0) {
return true;
}
return false;
}

/**
* 判斷該用戶是否有權請求該url
* @param royurl user擁有的授權的的url串集合
* @param url 當前請求的url
* @param reqmap 當前request的參數
* @return 是否通過該url
*/

protected boolean pass(Set royurl, String url, Map reqmap) {
boolean match = true;
for (Iterator iter = royurl.iterator(); iter.hasNext();) {
// 獲取資源
match = true;
String res_string = (String) iter.next();
if (res_string.indexOf("*") > 0) {
res_string = res_string.substring(0, res_string.indexOf("*"));
if (url.substring(0, res_string.length()).equalsIgnoreCase(res_string)) {
return true; //增加通配符比較
}
}
// 分割url與參數
String[] spw = res_string.split("\\?"); //用"\\?" 轉義后即可得到正確的結
if (url.indexOf(spw[0]) < 0) {//為了方便,沒有寫成spw[0].equals(url)
match = false;
}

if (match && spw.length > 1) {
String[] spa = spw[1].split("\\&"); // 分拆各參數
for (int j = 0; j < spa.length; j++) {
String[] spe = spa[j].split("="); // 分拆鍵與值
String key = spe[0];
String value = "";
if (spe.length > 1) {
value = spe[1].trim();
}
// 輪詢
String[] values = (String[]) reqmap.get(key);
if (values != null) {
for (int k = 0; k < values.length; k++) {
if (value.equalsIgnoreCase(values[k])) {
match = true;
break;
}
match = false;
}
if (!match) {
break;
}
}
}
}
if (match) {
break;
}
}
return match;
}

@SuppressWarnings("unchecked")
public static void main(String[] args) {
UrlFilter filter = new UrlFilter();
Set royurl = new HashSet();//可訪問的URL集合
royurl.add("/newsAction.do?typeId=1");
royurl.add("/newsAction.do?typeId=2");

//typeId為1時可以訪問,true
String url_1 = "/newsAction.do";
Map reqmap_1 = new HashMap();
reqmap_1.put("typeId", new String[]{"1"});
System.out.println("match false:" + filter.pass(royurl, url_1, reqmap_1));
//typeId為3時不可以訪問,false
String url_2 = "/newsAction.do";
Map reqmap_2 = new HashMap();
reqmap_2.put("typeId", new String[]{"3"});
System.out.println("match false:" + filter.pass(royurl, url_2, reqmap_2));
//url就不同,不可訪問,false
String url_3 = "/imageAction.do";
Map reqmap_3 = new HashMap();
reqmap_3.put("typeId", new String[]{"3"});
System.out.println("match false:" + filter.pass(royurl, url_3, reqmap_3));
}
}

配置 Servlet過濾器:
非常簡單,只需要在web.xml中加入類似下面的代碼就可將過濾器部署到應用程序。
<!--================權限 設置================-->
<filter>
<filter-name>Authentication</filter-name>
<filter-class>utils.UrlFilter</filter-class>
<init-param>
<param-name>onError</param-name>
<param-value>/index.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Authentication</filter-name>
<!-- 只過濾 .jsp 結尾的url, 其余的如 .do, .html, .jpg, .css 等不作過濾-->
<url-pattern>*.do</url-pattern>
</filter-mapping>
其中<filter-Class>是過濾器的路徑;<filter-mapping>定義了該過濾器只過濾以.do結尾的URL,當然你也可以稍做修改讓它過濾.jsp文件。
posted on 2007-08-29 12:40
楊愛友 閱讀(19908)
評論(3) 編輯 收藏 所屬分類:
java相關技術