|
servlet過濾器是小型的web組件,它能夠處理傳入的請求和傳出的響應(yīng)。Filter
不是一個servlet,它不能產(chǎn)生一個response,它能夠在一個request到達(dá)servlet之前預(yù)處理request,也可以在離開
servlet時處理response。它具有高度的透明性,無需更改應(yīng)用程序代碼,就可以根據(jù)需要添加、修改或從應(yīng)用程序中將它刪除。 一個filter 包括: 1. 在servlet被調(diào)用之前截獲; 2. 在servlet被調(diào)用之前檢查servlet request; 3. 根據(jù)需要修改request頭和request數(shù)據(jù); 4. 根據(jù)需要修改response頭和response數(shù)據(jù); 5. 在servlet被調(diào)用之后截獲. 你 能夠配置一個filter 到一個或多個servlet;單個servlet或servlet組能夠被多個filter 使用。幾個實用的filter包括:用戶辨認(rèn)filter,日志filter,審核filter,加密filter,符號filter,能改變xml內(nèi)容 的XSLT filter等。 一個客戶化的過濾器要實現(xiàn)Filter接口的三個方法:init()、destroy()和doFilter()。 1. init():在容器實例化過濾器時調(diào)用,該方法接受一個FilterConfig類型的對象做為輸入。 2. destroy():執(zhí)行一些清理操作。 3. doFilter():類似servlet的doPost()、doGet()方法,執(zhí)行具體的過濾任務(wù)。 下面給出一個可執(zhí)行程序范例,它包含main函數(shù),也可以部署到web應(yīng)用中。 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)) { //不需要判斷權(quán)限的請求如登錄頁面,則跳過 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);//判斷當(dāng)前user是否擁有訪問此url的權(quán)限 } } /** * * @param url 當(dāng)前請求的url * @param user 當(dāng)前登錄用戶 * @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");//為用戶分配訪問此地址的權(quán)限。在真正項目中,此Set集合可能要 //通過查詢數(shù)據(jù)庫user、role、menu等表,來獲取當(dāng)前用戶所擁有的全部可訪問資源 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,您沒有權(quán)限訪問該資源!</div>"); } }![]() /** * 是否需要判斷權(quán)限,如客戶端瀏覽、登錄頁面則不需要判斷權(quán)限 */![]() protected boolean noFileUrl(String url, HttpServletRequest request) { if (url.indexOf("/index.jsp") >= 0 || url.indexOf("login") > 0) { return true; } return false; }![]() /** * 判斷該用戶是否有權(quán)請求該url * @param royurl user擁有的授權(quán)的的url串集合 * @param url 當(dāng)前請求的url * @param reqmap 當(dāng)前request的參數(shù) * @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與參數(shù) String[] spw = res_string.split("\\?"); //用"\\?" 轉(zhuǎn)義后即可得到正確的結(jié) if (url.indexOf(spw[0]) < 0) {//為了方便,沒有寫成spw[0].equals(url) match = false; }![]() if (match && spw.length > 1) { String[] spa = spw[1].split("\\&"); // 分拆各參數(shù) 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過濾器: <!--================權(quán)限 設(shè)置================--> <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 結(jié)尾的url, 其余的如 .do, .html, .jpg, .css 等不作過濾--> <url-pattern>*.do</url-pattern> </filter-mapping> |
|
|