필터 응용 [인 코딩, 민감 어, 압축, 전의 필터]

머리말
위의 블 로그 에서 우 리 는 필터 의 기본 개념, 사용 및 간단 한 Servlet 응용 을 설명 했다.이 박문 은 주로 필터 의 고급 응용 을 설명 한다.
인 코딩 필터
목적: 전체 사이트 의 난 장 판 문 제 를 해결 합 니 다.
필터 개발

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        // request response   http   
        HttpServletRequest httpServletRequest = (HttpServletRequest) req;
        HttpServletResponse httpServletResponse = (HttpServletResponse) resp;

        httpServletRequest.setCharacterEncoding("UTF-8");
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("text/html;charset=UTF-8");
        
        chain.doFilter(httpServletRequest, httpServletResponse);
    }


첫 번 째 테스트
Servlet 1 에서 브 라 우 저 에 중국어 데 이 터 를 응답 하 였 으 며, 오류 가 발생 하지 않 았 습 니 다.

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.getWriter().write("      !");

    }

분석 하 다.
위의 필 터 는 완벽 하지 않 습 니 다. 브 라 우 저 는 get 방식 으로 서버 에 제출 한 중국어 데 이 터 를 위 에 있 는 필터 만 으로 는 완성 할 수 없습니다!
그럼 저희 가 어떻게 해 야 되 죠?우리 가 이전에 해결 한 get 방식 의 인 코딩 문 제 는 다음 과 같 습 니 다. request 를 사용 하여 전 달 된 데 이 터 를 가 져 오고 ISO 8859 - 1 인 코딩 을 통 해 인 코딩 이 아 닌 데 이 터 를 얻 을 수 있 습 니 다.
나의 이전의 박문 을 참고 하 다.https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=100000001&idx=6&sn=b0c346d7f17a097525ad106291aad28c&chksm=6bd740005ca0c916f72872122dff3bad8c49f9f690ea51b442b542dbbb654382bb663a01473b&mpshare=1&scene=1&srcid=0206hvswcHK67to1b4tr46AK#rd
Servlet 에서 브 라 우 저 를 가 져 와 GET 방식 으로 제출 한 중국어 가 난 장 판 의 근본 원인 은 getParameter () 방법 은 ISO 8859 - 1 의 인 코딩 으로 브 라 우 저가 전달 한 데 이 터 를 가 져 오 는 것 이 고 난 장 판 을 얻 는 것 이다.
근본 적 인 원인 을 알 았 으 니 하기 쉽 습 니 다. 필터 가 전달 하 는 request 대상 은 getParameter () 방법 을 사용 할 때 정상 적 인 중국어 데 이 터 를 얻 을 수 있 습 니 다.
즉, sun 회사 가 우리 에 게 제공 하 는 request 대상 은 부족 합 니 다. sun 회사 가 제공 하 는 request 대상 은 getParameter () 를 사용 하여 get 방식 으로 제출 한 데 이 터 를 가 져 오 는 것 은 어 지 러 운 코드 이기 때문에 우 리 는 request 대상 을 강화 해 야 합 니 다 (getParameter () 가 가 져 오 는 것 은 중국어 입 니 다)!
증강 request 대상
request 대상 을 강화 하려 면 포장 디자인 모델 을 사용 해 야 합 니 다!
포장 디자인 모델 의 다섯 가지 절차:
  • 1. 피 증강 대상 과 같은 인터페이스 실현
  • 2. 변 수 를 정의 하여 증강 대상 을 기억 합 니 다
  • 3. 구조 기 를 정의 하고 강화 대상
  • 을 받는다.
  • 4. 커버 를 강화 하 는 방법
  • 5. 강화 하고 싶 지 않 은 방법 에 대해 강화 대상 (목표 대상) 을 직접 호출 하 는 방법
  • sun 회사 도 우리 가 request 대상 의 방법 에 만족 하지 않 을 수 있다 는 것 을 알 고 Http ServletRequest Wrapper 류 를 제공 하여 우리 에 게 실현 시 켰 습 니 다 (Http ServletRequest 인 터 페 이 스 를 실현 한다 면 너무 많은 방법 을 실현 해 야 합 니 다!)
    
    
        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;
                }
        
                //    get   ,       
                if (!this.request.getMethod().equalsIgnoreCase("get")) {
                    return value;
                }
        
                try {
        
                    //       get  ,      
                    value = new String(value.getBytes("ISO8859-1"), this.request.getCharacterEncoding());
                    return value ;
        
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
        
                    throw new RuntimeException("      ");
                }
        
            }
        }
    
    

    강 화 된 request 대상 을 대상 자원 에 전달 합 니 다. 그러면 대상 자원 이 request 를 사용 하여 getParameter () 방법 을 호출 할 때 얻 은 것 은 중국어 데이터 입 니 다. 난호 가 아 닙 니 다!
    
            // request response   http   
            HttpServletRequest httpServletRequest = (HttpServletRequest) req;
            HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
    
            httpServletRequest.setCharacterEncoding("UTF-8");
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("text/html;charset=UTF-8");
    
            MyRequest myRequest = new MyRequest(httpServletRequest);
    
            //        request      。
            chain.doFilter(myRequest, httpServletResponse);
    

    이차 테스트
  • get 방식 으로 중국어 데 이 터 를 서버 에 전달
  • 
    

    민감 한 단어의 필터
    만약 에 사용자 가 민감 한 단어 (바보 b, 니 마, 개 떡 같은 문명 하지 않 은 언어 를 입력 했 을 때) 를 입력 하면 우 리 는 이런 문명 하지 않 은 것 을 차단 하고 기호 로 바 꿔 야 합 니 다!
    이러한 기능 을 실현 하 는 것 도 간단 합 니 다. 사용자 가 입력 한 민감 한 단 어 는 getParameter () 에서 얻 은 것 이 분명 합 니 다. 우 리 는 getParameter () 에서 이 데 이 터 를 얻 었 을 때 민감 한 단어 가 있 는 지 없 는 지 판단 하고 있 으 면 교체 하면 됩 니 다!쉽게 말 하면 request 대상 을 강화 해 야 한다.
    증강 request 대상
    
        class MyDirtyRequest extends HttpServletRequestWrapper {
        
            HttpServletRequest request;
        
            //        
            private List list = Arrays.asList(" b", "  ", "  ");
        
            public MyDirtyRequest(HttpServletRequest request) {
                super(request);
                this.request = request;
            }
        
            @Override
            public String getParameter(String name) {
        
                String value = this.request.getParameter(name);
        
                if (value == null) {
                    return null;
                }
        
                //  list  ,                
                for (String s : list) {
        
                    if (s.equals(value)) {
                        value = "*****";
                    }
                }
        
                return value ;
            }
        }
    

    필터 개발
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
            // request response   http   
            HttpServletRequest httpServletRequest = (HttpServletRequest) req;
            HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
    
            MyDirtyRequest dirtyRequest = new MyDirtyRequest(httpServletRequest);
    
            //              request  
            chain.doFilter(dirtyRequest, httpServletResponse);
        }
    

    테스트
    압축 자원 필터
    필터 의 실행 순서: 대상 자원 을 실행 하면 필터 뒤의 코드 가 실 행 됩 니 다.따라서 우 리 는 필터 에서 목표 자원 을 실행 한 후의 response 대상 을 가 져 올 수 있 습 니 다!
    sun 회사 가 제공 하 는 response 대상 이 write () 방법 을 호출 하 는 것 은 브 라 우 저 에 직접 데 이 터 를 되 돌려 주 는 것 임 을 알 고 있 습 니 다.압축 기능 을 실현 하려 면 write () 방법 으로 데 이 터 를 브 라 우 저 에 직접 쓸 수 없습니다!
    이것 은 위 와 유사 합 니 다. 필 터 를 대상 자원 에 전달 하 는 response 대상 은 우리 가 강화 해 야 합 니 다. 대상 자원 이 writer () 방법 을 호출 할 때 데 이 터 를 브 라 우 저 에 직접 쓰 지 않도록 해 야 합 니 다!
    증강 응답 대상
    response 대상 은 PrintWriter 나 ServletOutputStream 대상 을 사용 하여 writer () 방법 을 호출 할 수 있 습 니 다. 따라서 response 대상 을 강화 할 때 getOutputSteam 과 getWriter () 를 다시 써 야 합 니 다.
        
        class MyResponse extends HttpServletResponseWrapper{
        
            HttpServletResponse response;
            public MyResponse(HttpServletResponse response) {
                super(response);
                this.response = response;
            }
        
        
            @Override
            public ServletOutputStream getOutputStream() throws IOException {
                return super.getOutputStream();
            }
        
            @Override
            public PrintWriter getWriter() throws IOException {
                return super.getWriter();
            }
        }
    
    

    다음은 ServletOutputSteam 에서 writer () 방법 을 사용 하여 브 라 우 저 에 데 이 터 를 쓰 지 않도록 해 야 합 니 다.이것 은 또 우리 가 한 번 증강 해 야 한다!
    증강 ServletOutputSteam
    
        /*  ServletOutputSteam, writer              */
        class MyServletOutputStream extends ServletOutputStream{
        
            private ByteArrayOutputStream byteArrayOutputStream;
        
            public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
                this.byteArrayOutputStream = byteArrayOutputStream;
            }
        
            //   write()     ,       byteArrayOutputSteam 
            @Override
            public void write(int b) throws IOException {
                this.byteArrayOutputStream.write(b);
        
            }
        }
    
    

    증강 PrintWriter
    PrintWriter 대상 은 쉽게 처리 할 수 있 습 니 다. 그것 은 원래 포장 류 입 니 다. 구조 방법 을 보면 우 리 는 ByteArray OutputSteam 을 PrintWriter 에 직접 전달 할 수 있 습 니 다.
    
        @Override
        public PrintWriter getWriter() throws IOException {
            printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));
    
            return printWriter;
        }
    

    캐 시 데이터 가 져 오기
    우 리 는 데 이 터 를 모두 ByteArray OutputSteam 에 썼 습 니 다. 외부 캐 시 에 있 는 데 이 터 를 제공 하 는 방법 을 제공 해 야 합 니 다!
    
        public byte[] getBuffer() {
    
            try {
    
                //        ,     !
                if (printWriter != null) {
                    printWriter.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.flush();
                    return byteArrayOutputStream.toByteArray();
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    

    response 의 전체 코드 강화
    
    class MyResponse extends HttpServletResponseWrapper{
    
        private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    
        private PrintWriter printWriter ;
    
        private HttpServletResponse response;
        public MyResponse(HttpServletResponse response) {
            super(response);
            this.response = response;
        }
    
    
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
    
            //   ServletOutputSteam    write()     ,      byteArrayOutputSteam  
            return new MyServletOutputStream(byteArrayOutputStream);
        }
    
        @Override
        public PrintWriter getWriter() throws IOException {
            printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));
    
            return printWriter;
        }
    
        public byte[] getBuffer() {
    
            try {
    
                //        ,     !
                if (printWriter != null) {
                    printWriter.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.flush();
                    return byteArrayOutputStream.toByteArray();
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    필터
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
    
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            MyResponse myResponse = new MyResponse(response);
    
            //     response      ,      write()                    
            chain.doFilter(request, myResponse);
    
            //                 
            byte[] bytes = myResponse.getBuffer();
    
            //       
            System.out.println("   :"+bytes.length);
    
            
            //  GZIP     ,       
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
            gzipOutputStream.write(bytes);
            gzipOutputStream.flush();
            
            //        
            byte[] gzip = byteArrayOutputStream.toByteArray();
            
            System.out.println("   :" + gzip.length);
            
            //     ,     ,      !
            response.setHeader("content-encoding", "gzip");
            response.setContentLength(gzip.length);
            response.getOutputStream().write(gzip);
         
        }
    

    테스트
  • Servlet 에 큰 텍스트 를 출력 합 니 다:
  •     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            response.getWriter().write("fdshfidsuhfidusfhuidsfhuidshdsuifhsd" +
                    "uifhsduifffffdshfidsuhfidusfhuidsfhuidshdsuif" +
                    "hsduifhsduifffffdshfidsuhfidusfhuidsfhuidshd" +
                    "suifhsduifhsduifffffdshfidsuhfidusfhuidsfhuidsh" +
                    "dsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhuids" +
                    "hdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhuid" +
                    "shdsuifhsduifhsduiffdshfidsuhfidusfhuidsfhuids" +
                    "hdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhui" +
                    "dshdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfh" +
                    "uidshdsuifhsduifhsduifffffdshfidsuhfidusfhuids" +
                    "fhuidshdsuifhsduifhsduifffffdshfidsuhfidusfhuid" +
                    "sfhuidshdsuifhsduifhsduifffffdshfidsuhfidusfhui" +
                    "dsfhuidshdsuifhsduifhsduifffffdshfidsuhfidusfh" +
                    "uidsfhuidshdsuifhsduifhsduifffffdshfidsuhfidusf" +
                    "huidsfhuidshdsuifhsduifhsduifffffdshfidsuhfidus" +
                    "fhuidsfhuidshdsuifhsduifhsduifffffdshfidsuhfid" +
                    "usfhuidsfhuidshdsuifhsduifhsduifffffdshfidsuhf" +
                    "idusfhuidsfhuidshdsuifhsduifhsd" +
                    "uifffffdshfidsuhfidusfhuidsfhuidshdsuifhsduifhsduifffffff");
    
        }
    
  • 효과:
  • HTML 전의 필터
    getParameter () 에서 얻 은 데 이 터 를 한 번 만 바 꾸 면 기능 을 완성 할 수 있 습 니 다.
    증강 요청
    
    
    class MyHtmlRequest extends HttpServletRequestWrapper{
    
        private HttpServletRequest request;
    
        public MyHtmlRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }
    
    
        @Override
        public String getParameter(String name) {
    
            String value = this.request.getParameter(name);
            return this.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;
                    default:
                        result.append(content[i]);
                }
            }
            return (result.toString());
            
        }
        
    }
    

    필터
    
    
    
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
    
    
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            MyHtmlRequest myHtmlRequest = new MyHtmlRequest(request);
    
            //        request!
            chain.doFilter(myHtmlRequest, response);
    
        }
    

    테스트
    jsp 코드:
    
        

    Servlet 코드:
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            String value = request.getParameter("username");
            response.getWriter().write(value);
    
        }
    

    메모리 에 데 이 터 를 캐 시 합 니 다.
    앞에서 우 리 는 브 라 우 저가 데 이 터 를 캐 시 하지 않도록 했 습 니 다. [인증 코드 의 그림 은 캐 시 하지 말 아야 합 니 다.]
    지금 우리 가 해 야 할 일 은 캐 시 데 이 터 를 메모리 에 저장 하 는 것 입 니 다.
    이것 은 데 이 터 를 압축 한 Filter 와 매우 유사 합 니 다. 데 이 터 를 브 라 우 저 에 직접 출력 하지 않 고 용기 (ByteArray OutputSteam) 로 저장 하기 때 문 입 니 다.캐 시 가 있 으 면 캐 시 를 가 져 옵 니 다.캐 시 없 이 대상 자원 을 실행 합 니 다!
    증강 응답 대상
    class MyResponse extends HttpServletResponseWrapper {
    
        private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    
        private PrintWriter printWriter ;
    
        private HttpServletResponse response;
        public MyResponse(HttpServletResponse response) {
            super(response);
            this.response = response;
        }
    
    
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
    
            //   ServletOutputSteam    write()     ,      byteArrayOutputSteam  
            return new MyServletOutputStream(byteArrayOutputStream);
        }
    
        @Override
        public PrintWriter getWriter() throws IOException {
            printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));
    
            return printWriter;
        }
    
        public byte[] getBuffer() {
    
            try {
    
                //        ,     !
                if (printWriter != null) {
                    printWriter.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.flush();
                    return byteArrayOutputStream.toByteArray();
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    
    //  ServletOutputSteam, writer              
    
    class MyServletOutputStream extends ServletOutputStream {
    
        private ByteArrayOutputStream byteArrayOutputStream;
    
        public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
            this.byteArrayOutputStream = byteArrayOutputStream;
        }
    
        //   write()     ,       byteArrayOutputSteam 
        @Override
        public void write(int b) throws IOException {
            this.byteArrayOutputStream.write(b);
    
        }
    }
    

    필터
    
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
            //    Map  ,key      ,value      
            Map map = new HashMap<>();
    
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
    
            //            
            String uri = request.getRequestURI();
            byte[] bytes = map.get(uri);
    
            //     ,           ,          
            if (bytes != null) {
                response.getOutputStream().write(bytes);
                return ;
            }
    
            //      ,      
            MyResponse myResponse = new MyResponse(response);
            chain.doFilter(request, myResponse);
    
            //                 
            byte[] b = myResponse.getBuffer();
    
            //        
            map.put(uri, b);
    
            //         
            response.getOutputStream().write(b);
    
    
        }
    

    테스트
    새로 고침 에 도 불구 하고 캐 시 에서 얻 은 데 이 터 를 가 져 옵 니 다!
    글 에 잘못된 부분 이 있 으 면 지적 을 환영 하고 서로 교류 합 니 다.위 챗 에서 기술 문장 을 보 는 습관 이 있 는 학생 들 은 위 챗 공식 번호: 자바 3y 에 주목 할 수 있 습 니 다.

    좋은 웹페이지 즐겨찾기