현재 진행하고 있는 프로젝트가 있습니다. 여기서 경매글을 등록해야 하는데, 이 부분이 html로 이루어져 있습니다.

html로 구현을 했기 때문에 XSS를 방지할 필요성이 있습니다.

 

XSS를 간단하게 설명하면 html의 script, iframe 태그 등을 이용하여 해커가 원하는 코드를 넣을 수 있습니다.

그렇기 때문에 이런 태그들을 허용하면 안 됩니다. 그래서 jsoup을 이용해서 파싱 했습니다.

 

@Override
public String processContent(String content, List<MultipartFile> files) {
    assertNotXSS(content);
    ...
}
private void assertNotXSS(String content) {
    String tar = Jsoup.clean(content, BASE_URL, Safelist.relaxed().preserveRelativeLinks(true));

    if (!tar.equals(content)) {
        throw new AuctionException(AuctionExceptionType.INVALID_AUCTION_CONTENT);
    }
}

이런 식으로 하면 파싱이 가능합니다.

 

파싱이 된 string과 입력으로 온 string이 다른 경우 예외가 발생하게 됩니다.

 

아래는 테스트 코드입니다.

@Test
@DisplayName("XSS 방지 테스트")
public void XSSTest() throws IOException {
    List<MultipartFile> imgs = getFiles(imgPath);
    String content = "<script>console.log(\"hi\");</script></h1><img src=\"1.png\"><img src=\"2.jpg\">";
    assertThrows(AuctionException.class,()->auctionContentHandler.processContent(content,imgs));
}

이처럼 script 태그가 있을 경우에 예외가 발생합니다.

성공적으로 처리하는 것을 알 수 있습니다.(결과를 보여드리기 위해서 파싱하고 print 하게 했습니다. 원래 코드에서는 print 하지 않습니다.)

 

@Test
@DisplayName("정상적으로 처리하는 지 테스트")
public void test() throws IOException {
    List<MultipartFile> imgs = getFiles(imgPath);

    String content = "<h1>\"asdf\"</h1><img src=\"1.png\"><img src=\"2.jpg\">";
    List<String> originalAttr = getHtmlImgAttr(content);

    ret = auctionContentHandler.processContent(content, imgs);
    List<String> afterAttr = getHtmlImgAttr(ret);


    for (int i = 0; i < originalAttr.size(); i++) {
        System.out.printf("%s -> %s%n", originalAttr.get(i), afterAttr.get(i));
        File changedFile = new File(CHANGE_IMG_PATH + "/" + afterAttr.get(i));
        assertTrue(changedFile.exists());
        assertNotEquals(originalAttr.get(i), afterAttr.get(i));
    }
    System.out.println(content);
    System.out.println(ret);
}

이는 정상적인 경매내용이 들어올 경우 테스트합니다.

클라이언트로부터 이미지 파일과 html이 입력으로 오면, 로컬에 파일을 저장합니다.(이 때 파일 이름은 UUID를 이용합니다.)

그리고 html의 img 태그의 attribute를 저장한 파일 이름으로 변경해 줍니다.

 

결과입니다. 실제로 파일이름이 변경되었고, 이 파일이 존재하는지 테스트했을 때 통과했습니다.

jsoup을 이용하여 string을 document로 만들면 <html> <head> <body>가 붙네요.

 

 

 

 

테스트 코드를 이렇게 작성하는 것이 맞는 건지 잘 모르겠네요. 너무 특정 기술에 의존하고 있어서 걸리네요.

만약 html이 아니라 md로 바꾼다거나 아니면 이미지를 로컬에 파일로 저장하지 않고 다른 곳에 저장하게 되면 테스트 코드의 변경이 일어나게 됩니다.

좋은 테스트 코드 작성이 진짜 어렵네요.

반응형

+ Recent posts