zoukankan      html  css  js  c++  java
  • servlet中filter(过滤器)的学习使用

    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));
        }
    }
    View Code

    配置 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> 
    View Code

    其中<filter-Class>是过滤器的路径;<filter-mapping>定义了该过滤器只过滤以.do结尾的URL,当然你也可以稍做修改让它过滤.jsp文件。

  • 相关阅读:
    HttpClient访问的策略Policy
    Fiddler 工具使用技巧
    设置Chrome浏览器User-Agent
    anaconda Script file Scriptspip-script.py is not present
    anaconda3+ paddleOCR安装使用
    anaconda 创建虚环境 必须指定python版本
    pyqt 启动GUI前启动子进程,退出GUI后退出子进程
    pyqt 扩展QsciScintilla disable mouse select
    pyqt designer下添加QsciScintilla 控件
    rdkit 读mol时保留H原子
  • 原文地址:https://www.cnblogs.com/zhang-cb/p/6112511.html
Copyright © 2011-2022 走看看