I.K.Picture & IT Info.

자바 기반 웹 서비스 수행 시 주소 창 직접 접근 막는 법 (URL 직접 접근 막는법) 본문

Development/Web

자바 기반 웹 서비스 수행 시 주소 창 직접 접근 막는 법 (URL 직접 접근 막는법)

helpful-intruder 2020. 3. 19. 14:11
반응형

전, 자바로 웹 서비스를 많이 구축하고 있는데요.

문득 이런생각이 들었어요..

 

다운로드를 막기 위해 실제 서비스에 뷰어 기능만 넣어서 직접 보여주는데

이를 다운로드 하고 싶어... 데이터를 불러오는 API를 분석? 하여 다운로드할 경우 가능할까??

 

당연히 가능하죠, 일반 사용자분들은 단순 클릭해서 서비스를 접근하지만 

간혹 머리 좋으신 분들... 또는 개발자 분들..은 개발 툴을 활용하면 JavaScript 내용을 볼 수 있고 

이를 분석하면 api url 찾는건 뭐 금방일꺼같습니다. .. 그쵸?

이걸 일반 주소창을 막겠따고 GET은 다 막고 POST로 한다고해도.. POST 요청 어플리케이션을 쓴다면...

막는다고 볼수는 없습니다...

 

이걸 그럼 어떻게 막을까요??

일단 전 GET 형태에서 자바 쪽에 다음과 같이 작업을 수행하였습니다. 

 

접근이되는 해당 컨트롤러에 있는 HttpServletRequest Header 값을 파악하면되더라구요 

 

예를들어 pdf 파일을 뷰어하기 위해 (실제로는 다운로드 기능이라고 보면되겠습니다)

아래와 같이 소스코드를 작성해놓았습니다.  ( 다운로드 기능 찾고 계신 분이라면 이거 참고하시면되요 :) )

   @RequestMapping(value="/pdf/{type}/{path:.+}")
    public ResponseEntity viewFile(@PathVariable String type, @PathVariable String path, HttpServletRequest request) {
            File f = new File(root + type + File.separator + path);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/pdf"));
            headers.add("Access-Control-Allow-Origin", "*");
            headers.add("Access-Control-Allow-Methods", "GET, POST, PUT");
            headers.add("Access-Control-Allow-Headers", "Content-Type");
            headers.add("Content-Disposition", "filename=" + path);
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");
            logger.info("Viewing file at " + path + ", ip: " + request.getRemoteAddr());
            ResponseEntity response = null;
            try {
                headers.setContentLength(f.length());
                response = new ResponseEntity(
                        new InputStreamResource(new FileInputStream(f)), headers, HttpStatus.OK);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return response;
    }

 

이 소스코드도 전혀 문제가 없습니다. pdf파일이 아주 잘 다운로드 받아지죠

(뷰어 기능이 서비스에 있을 경우 바로 잘 보여집니다)

 

그런데 주소창에 ( .../pdf/aaa/aaa.pdf ) 라고 쳐도 데이터가 다운로드 받아지겠죠~?

뭐 이건 당연한 얘기입니다. 

다시 말씀드리지만 전 이 부분을 막고싶었던겁니다. 

생각보다 그리 어렵지 않아요.

바로 아래 부분만 추가하면됩니다. 

if (request.getHeader("REFERER") == null){ ...  }

if 안 내용에다가는 처리할 내용을 작성하면됩니다. 

저 같은 경우엔 pdf 다운로드를 막는 부분이였기 때문에 

임시 pdf 파일로 대체를 했습니다. (view.pdf 파일에는 다운로드는 불가능합니다.. 라는 설명이 들어가 있는 pdf 예요)

REFERER 이라는 키 값을 가진 해더 부분이 클릭을 했을 때는 어떤 값이라도 포함이 되서 넘어오지만

주소 창에서 직접 요청할 경우 null 값으로 넘어오게 되더군요.

 

이 차이를 이용한 것입니다. 

 

아래 풀 소스코드입니다. 

 @RequestMapping(value="/pdf/{type}/{path:.+}") 
 public ResponseEntity viewFile(@PathVariable String type, @PathVariable String path, HttpServletRequest request) { 
            File f = new File(root + type + File.separator + path); 
            HttpHeaders headers = new HttpHeaders(); 
            headers.setContentType(MediaType.parseMediaType("application/pdf")); 
            headers.add("Access-Control-Allow-Origin", "*"); 
            headers.add("Access-Control-Allow-Methods", "GET, POST, PUT"); 
            headers.add("Access-Control-Allow-Headers", "Content-Type"); 
            headers.add("Content-Disposition", "filename=" + path); 
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate"); 
            headers.add("Pragma", "no-cache"); 
            headers.add("Expires", "0"); 
            logger.info("Viewing file at " + path + ", ip: " + request.getRemoteAddr()); 
            ResponseEntity response = null; 

            if (request.getHeader("REFERER") == null){
                logger.info("Direct Access: " + path + ", ip: " + request.getRemoteAddr());
                f = new File(root + File.separator + "view.pdf");
                headers.add("Content-Disposition", "filename=" + path);
            }


            try { 
                headers.setContentLength(f.length()); 
                response = new ResponseEntity( 
                        new InputStreamResource(new FileInputStream(f)), headers, HttpStatus.OK); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            return response; 
    } 

 

여기서 보여지는 root 변수는 당연히 파일이 저장되어 있는 path String 변수예요.

 

반응형
Comments