zoukankan      html  css  js  c++  java
  • java之过滤器Filter (应用场景)

      filter在开发中的常见应用:
         * 1.filter可以目标资源执行之前,进行权限检查,检查用户有无权限,如有权限则放行,如没有,则拒绝访问
         * 2.filter可以放行之前,对request和response进行预处理,从而实现一些全局性的设置。
         * 3.filter在放行之后,可以捕获到目标资源的输出,从而对输出作出类似于压缩这样的设置

    一、解决全网站的乱码:

    public void doFilter(ServletRequest req, ServletResponse resp,  
            FilterChain chain) throws IOException, ServletException {  
          
        HttpServletRequest request = (HttpServletRequest) req;  
        HttpServletResponse response = (HttpServletResponse) resp;  
          
        request.setCharacterEncoding("UTF-8");  //这个编码只能解决Post提交,不能解决get方式的提交,所以需要对request中getParameter  
                                               //方法增强  
        response.setCharacterEncoding("UTF-8");  
        response.setContentType("text/html;charset=UTF-8");  
          
        chain.doFilter(new MyRequest(request), response);   //request.getparameter("password");  
    }  
      
    /* 
    1.写一个类,实现与被增强对象相同的接口 
    2.定义一个变量,记住被增强对象 
    3.定义一个构造方法,接收被增强对象 
    4.覆盖想增强的方法 
    5.对于不想增强的方法,直接调用被增强对象(目标对象)的方法 
     */  
      
    class MyRequest extends HttpServletRequestWrapper{  
      
        private HttpServletRequest request;  
        public MyRequest(HttpServletRequest request) {  
            super(request);  
            this.request = request;  
        }  
        @Override  
        public String getParameter(String name) {  
              
            String value = this.request.getParameter(name);  
            if(!request.getMethod().equalsIgnoreCase("get")){  
                return value;  
            }  
              
            if(value==null){  
                return null;  
            }  
              
            try {  
                return value = new String(value.getBytes("iso8859-1"),request.getCharacterEncoding());  
            } catch (UnsupportedEncodingException e) {  
                throw new RuntimeException(e);  
            }  
              
        }  
          
        }  
    

      二,实现自动登录

            实现用户自动登陆的过滤器
           在用户登陆成功后,发送一个名称为user的cookie给客户端,cookie的值为用户名和md5加密后的密码。编写一个AutoLoginFilter,这个filter检查用户是否带有名称为user的cookie来,如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配,匹配则向session中存入user对象(即用户登陆标记),以实现程序完成自动登陆。

    public void doFilter(ServletRequest req, ServletResponse resp,  
                FilterChain chain) throws IOException, ServletException {  
               
              
              
            HttpServletRequest request = (HttpServletRequest) req;  
            HttpServletResponse response = (HttpServletResponse) resp;  
              
            //1.先检查用户是否已登陆,没登陆才自动登陆  
            User user = (User) request.getSession().getAttribute("user");  
              
            if(user!=null){  
                chain.doFilter(request, response);  
                return;  
            }  
              
            //2.没登陆,再执行自动登陆逻辑  
              
            //看用户有没有带自动登陆的cookie  
            Cookie autoLoginCookie = null;  
            Cookie cookies[] = request.getCookies();  
              
            for(int i=0;cookies!=null && i<cookies.length;i++){  
                if(cookies[i].getName().equals("autologin")){  
                    autoLoginCookie = cookies[i];  
                }  
            }  
            if(autoLoginCookie==null){  
                chain.doFilter(request, response);  
                return;  
            }  
              
            //用户带了自动登陆的cookie,则先检查cookie的有效期   
            String values[] = autoLoginCookie.getValue().split("\:");  
            if(values.length!=3){  
                chain.doFilter(request, response);  
                return;  
            }  
            long expirestime = Long.parseLong(values[1]);  
            if(System.currentTimeMillis()>expirestime){  
                chain.doFilter(request, response);  
                return;  
            }  
          
            //代表cookie时间有效,再检查cookie的有效性  
            String username = values[0];  
            String client_md5 = values[2];  
              
            BusinessService service = new BusinessService();  
            user = service.findUser(username);  
            if(user==null){  
                chain.doFilter(request, response);  
                return;  
            }  
            ////autologin=username:expirestime:md5(password:expirestime:username)  
            String server_md5 = md5(user.getUsername(),user.getPassword(),expirestime);  
            if(!server_md5.equals(client_md5)){  
                chain.doFilter(request, response);  
                return;  
            }  
              
            //执行登陆  
            request.getSession().setAttribute("user", user);  
            chain.doFilter(request, response);  
              
        }  
          
        private String md5(String username,String password,long expirestime){  
              
            try{  
                String value = password + ":" + expirestime + ":" + username;  
                MessageDigest md = MessageDigest.getInstance("md5");  
                byte md5[] = md.digest(value.getBytes());  
                BASE64Encoder encode = new BASE64Encoder();  
                return encode.encode(md5);  
            }catch (Exception e) {  
                throw new RuntimeException(e);  
            }  
        }  
    

      

    public void doGet(HttpServletRequest request, HttpServletResponse response)  
                throws ServletException, IOException {  
      
            String username = request.getParameter("username");  
            String password = request.getParameter("password");  
              
            BusinessService service = new BusinessService();  
            User user = service.login(username, password);  
            if(user==null){  
                request.setAttribute("message", "用户名或密码错误!!");  
                request.getRequestDispatcher("/message.jsp").forward(request, response);  
                return;  
            }  
              
            request.getSession().setAttribute("user", user);  
            int expirestime = Integer.parseInt(request.getParameter("time"));  
            //给客户机发送自动登陆的 cookie    
            //autologin=username:expirestime:md5(password:expirestime:username)  
            Cookie cookie = makeCookie(user, expirestime);  
            response.addCookie(cookie);  
            response.sendRedirect("/login/index.jsp");  
        }  
          
        public Cookie makeCookie(User user,int expirestime){  
            long currenttime = System.currentTimeMillis();  
            String cookieValue = user.getUsername() + ":" + (currenttime+expirestime*1000) + ":" + md5(user.getUsername(), user.getPassword(), (currenttime+expirestime*1000));  
            Cookie cookie = new Cookie("autologin",cookieValue);  
            cookie.setMaxAge(expirestime);  
            cookie.setPath("/login");  
            return cookie;  
        }  
          
        private String md5(String username,String password,long expirestime){  
              
            try{  
                String value = password + ":" + expirestime + ":" + username;  
                MessageDigest md = MessageDigest.getInstance("md5");  
                byte md5[] = md.digest(value.getBytes());  
                BASE64Encoder encode = new BASE64Encoder();  
                return encode.encode(md5);  
            }catch (Exception e) {  
                throw new RuntimeException(e);  
            }  
        }  
    

      三,禁止浏览器缓存所有动态页面的过滤器:
            有 3 个 HTTP 响应头字段都可以禁止浏览器缓存当前页面,它们在 Servlet 中的示例代码如下:
                 response.setDateHeader("Expires",-1);
                 response.setHeader("Cache-Control","no-cache"); 
                 response.setHeader("Pragma","no-cache"); 
           并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头。
                 Expires数据头:值为GMT时间值,为-1指浏览器不要缓存页面
                 Cache-Control响应头有两个常用值:
                 no-cache指浏览器不要缓存当前页面。
                 max-age:xxx指浏览器缓存页面xxx秒。

    四,控制浏览器缓存页面中的静态资源的过滤器:
            有些动态页面中引用了一些图片或css文件以修饰页面效果,这些图片和css文件经常是不变化的,所以为减轻服务器的压力,可以使用filter控制浏览器缓存这些文件,以提升服务器的性能。

    private Map<String,byte[]> map = new HashMap();  
          
        public void doFilter(ServletRequest req, ServletResponse resp,  
                FilterChain chain) throws IOException, ServletException {  
              
            HttpServletRequest request = (HttpServletRequest) req;  
            HttpServletResponse response = (HttpServletResponse) resp;  
              
            //1.得到用户想访问的资源(uri)  
            String uri = request.getRequestURI();  
              
            //2.看map集合中是否保存了该资源的数据  
            byte b[] = map.get(uri);  
              
            //3.如果保存了,则直接取数据打给浏览器  
            if(b!=null){  
                response.getOutputStream().write(b);  
                return;  
            }  
              
            //4.如果没有保存数据,则放行让目标资源执行,这时还需写一个response的包装类,捕获目标资源的输出  
            MyResponse my = new MyResponse(response);  
            chain.doFilter(request, my);  
            byte data[] = my.getBuffer();  
              
            //5.以资源uri为关键字,打资源的数据保存map集合中,以备于下次访问  
            map.put(uri, data);  
              
            //6.输出数据给浏览器  
            response.getOutputStream().write(data);  
              
              
      
        }  
          
        class MyResponse extends HttpServletResponseWrapper{  
            private ByteArrayOutputStream bout = new ByteArrayOutputStream();  
            private PrintWriter pw;  
              
            private HttpServletResponse response;  
            public MyResponse(HttpServletResponse response) {  
                super(response);  
                this.response = response;  
            }  
            @Override  
            public ServletOutputStream getOutputStream() throws IOException {  
                return new MyServletOutputStream(bout);    //myresponse.getOutputStream().write("hahah");  
            }  
              
            @Override  
            public PrintWriter getWriter() throws IOException {  
                pw = new PrintWriter(new OutputStreamWriter(bout,response.getCharacterEncoding()));  
                return pw;    
            }  
            public byte[] getBuffer(){  
                if(pw!=null){  
                    pw.close();  
                }  
                return bout.toByteArray();  
            }  
        }  
          
        class MyServletOutputStream extends ServletOutputStream{  
      
            private ByteArrayOutputStream bout;  
            public MyServletOutputStream(ByteArrayOutputStream bout){  
                this.bout = bout;  
            }  
            @Override  
            public void write(int b) throws IOException {  
                bout.write(b);  
            }  
              
        }  
    

      五、使用Decorator模式包装request对象,实现html标签转义功能(Tomcat服务器中提供了转义html标签的工具类)

    public void doFilter(ServletRequest req, ServletResponse resp,  
                FilterChain chain) throws IOException, ServletException {  
              
            HttpServletRequest request = (HttpServletRequest) req;  
            HttpServletResponse response = (HttpServletResponse) resp;  
              
            chain.doFilter(new MyRequest(request), response);  //request.getParameter("resume");  //<script>  
              
      
        }  
          
        class MyRequest extends HttpServletRequestWrapper{  
            private HttpServletRequest request;  
            public MyRequest(HttpServletRequest request) {  
                super(request);  
                this.request = request;  
            }  
            @Override  
            public String getParameter(String name) {  
                  
                String value = this.request.getParameter(name);  
                if(value==null){  
                    return null;  
                }  
                return filter(value);  
            }  
              
            public String filter(String message) {  
      
                if (message == null)  
                    return (null);  
      
                char content[] = new char[message.length()];  
                message.getChars(0, message.length(), content, 0);  
                StringBuffer result = new StringBuffer(content.length + 50);  
                for (int i = 0; i < content.length; i++) {  
                    switch (content[i]) {  
                    case '<':  
                        result.append("<");  
                        break;  
                    case '>':  
                        result.append(">");  
                        break;  
                    case '&':  
                        result.append("&");  
                        break;  
                    case '"':  
                        result.append(""");  
                        break;  
                    default:  
                        result.append(content[i]);  
                    }  
                }  
                return (result.toString());  
      
            }  
    }  
    

      六、压缩响应信息

           服务器发给浏览器的数据时,先进行压缩,然后在发出,(注意filter要拦截的对象,都会压缩,所以要在web.xml中配置好想要拦截的对象)。

    public void doFilter(ServletRequest req, ServletResponse resp,  
                FilterChain chain) throws IOException, ServletException {  
              
            HttpServletRequest request = (HttpServletRequest) req;  
            HttpServletResponse response = (HttpServletResponse) resp;  
            MyResponse myresponse = new MyResponse(response);  
              
              
            chain.doFilter(request, myresponse);  //response.getwriter  response.getOutputStream    
              
            //取出缓冲的数据压缩后输出  
            byte out[] = myresponse.getBuffer();  //得到目标资源的输出  
            byte gzipout[] = gzip(out);  
            response.setHeader("content-encoding", "gzip");  
            response.setHeader("content-length", gzipout.length + "");  
            response.getOutputStream().write(gzipout);  
        }  
          
        public byte[] gzip(byte b[]) throws IOException{  
              
            ByteArrayOutputStream bout = new ByteArrayOutputStream();  
            GZIPOutputStream gout = new GZIPOutputStream(bout);  
            gout.write(b);  
            gout.close();  
            return bout.toByteArray();  
        }  
          
        class MyResponse extends HttpServletResponseWrapper{  
            private ByteArrayOutputStream bout = new ByteArrayOutputStream();  
            private PrintWriter pw;  
              
            private HttpServletResponse response;  
            public MyResponse(HttpServletResponse response) {  
                super(response);  
                this.response = response;  
            }  
            @Override  
            public ServletOutputStream getOutputStream() throws IOException {  
                return new MyServletOutputStream(bout);    //myresponse.getOutputStream().write("hahah");  
            }  
              
            @Override  
            public PrintWriter getWriter() throws IOException {  
                pw = new PrintWriter(new OutputStreamWriter(bout,response.getCharacterEncoding()));  
                return pw;    
            }  
            public byte[] getBuffer(){  
                if(pw!=null){  
                    pw.close();  
                }  
                return bout.toByteArray();  
            }  
        }  
          
        class MyServletOutputStream extends ServletOutputStream{  
      
            private ByteArrayOutputStream bout;  
            public MyServletOutputStream(ByteArrayOutputStream bout){  
                this.bout = bout;  
            }  
            @Override  
            public void write(int b) throws IOException {  
                bout.write(b);  
            }  
              
        }  
    

      七、敏感词过滤(z注意词库中词语的格式:例如:傻逼|1   后面的1表示识别词库中的等级 ,禁用词为1,审查词为2,替换词为3)

    private List<String> banWords = new ArrayList();//禁用词,例如:傻逼|1    
        private List<String> auditWords = new ArrayList();//审查词   例如: 中共|2  
        private List<String> replaceWords = new ArrayList();//替换词  例如: 色情|3  
          
        public void init(FilterConfig filterConfig) throws ServletException {  
            try{  
                String path = WordsFilter.class.getClassLoader().getResource("cn/xxx/xxx").getPath();//地址表词库存放在那个包下面  
                File files[] =  new File(path).listFiles();  
                for(File file : files){  
                    if(!file.getName().endsWith(".txt")){//表示词库的后缀名文件  
                        continue;  
                    }  
                    BufferedReader br = new BufferedReader(new FileReader(file));  
                    String line = null;  
                    while((line=br.readLine())!=null){  
                        String s[] = line.split("\|");  
                        if(s.length!=2){  
                            continue;  
                        }  
                        if(s[1].trim().equals("1")){  
                            banWords.add(s[0].trim());  
                        }  
                          
                        if(s[1].trim().equals("2")){  
                            auditWords.add(s[0].trim());  
                        }  
                          
                        if(s[1].trim().equals("3")){  
                            replaceWords.add(s[0].trim());  
                        }  
                    }  
                }  
                System.out.println("haha");  
            }catch (Exception e) {  
                throw new RuntimeException(e);  
            }  
      
        }  
          
        public void doFilter(ServletRequest req, ServletResponse resp,  
                FilterChain chain) throws IOException, ServletException {  
      
            HttpServletRequest request = (HttpServletRequest) req;  
            HttpServletResponse response = (HttpServletResponse) resp;  
              
            //检查提交数据是否包含禁用词  
            Enumeration e = request.getParameterNames();  
            while(e.hasMoreElements()){  
                String name = (String) e.nextElement();  
                String data = request.getParameter(name);   
                for(String regex : banWords){  
                    Pattern pattern = Pattern.compile(regex);  
                    Matcher m = pattern.matcher(data);  
                    if(m.find()){  
                        request.setAttribute("message", "文章中包括非法词汇,请检查后再提交!!");  
                        request.getRequestDispatcher("/message.jsp").forward(request, response);  
                        return;  
                    }  
                }  
            }  
              
            //检查审核词  
              
            //检查替换词  
            chain.doFilter(new MyRequest(request), response);  
              
        }  
          
          
        class MyRequest extends HttpServletRequestWrapper{  
            private HttpServletRequest request;  
            public MyRequest(HttpServletRequest request) {  
                super(request);  
                this.request = request;  
            }  
            @Override  
            public String getParameter(String name) {  
                  
                String data = this.request.getParameter(name);  
                if(data==null){  
                    return null;  
                }  
                for(String regex : auditWords){//检查审核词  
                    Pattern p = Pattern.compile(regex);  
                    Matcher m = p.matcher(data);  
                    if(m.find()){      
                        String value = m.group();  //找出客户机提交的数据中和正则表达式相匹配的数据  
                        data = data.replaceAll(regex, "<font color='red'>" + value + "</font>");  
                    }  
                }  
                  
                  
                for(String regex : replaceWords){//检查替换词  
                    Pattern p = Pattern.compile(regex);  
                    Matcher m = p.matcher(data);  
                    if(m.find()){     
                        data = data.replaceAll(regex, "*******");  
                    }  
                }  
                  
                return data;  
            }  
        }  
    

      

  • 相关阅读:
    导出redis中某个大key中的值并与数据库中作对比
    添加印记脚本
    校园信息流读请求脚本
    每天一个linux命令(1):which命令(转)
    (转)Jmeter内存溢出处理方式记录
    提升效率(时间准确性),减少时间和资源的消耗——由89C52/89C51的定时器中断引出的一些问题
    STM32重映射(PinRemap)的使用,注意!
    Terminal中输入命令直接打开QtCreator,以及创建其桌面快捷方式
    MarkDown插入图片
    初试MarkDown
  • 原文地址:https://www.cnblogs.com/zhangyongJava/p/8296976.html
Copyright © 2011-2022 走看看