게시글 제목, 내용에 대한 특수문자(태그포함) 및 XSS 처리 통합자료관과 통일성있게 변경 처리
This commit is contained in:
parent
22f543a91a
commit
3c29a91a59
@ -93,8 +93,8 @@ public class ArticleVO extends PagingVO {
|
||||
return attachFiles.size();
|
||||
}
|
||||
|
||||
public String getUnescapedContent() {
|
||||
return StringEscapeUtils.unescapeHtml(content);
|
||||
public String getSanitizedContent() {
|
||||
return StringUtil.sanitizeHtml(content);
|
||||
}
|
||||
|
||||
// SETTER & GETTER
|
||||
@ -126,7 +126,14 @@ public class ArticleVO extends PagingVO {
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
|
||||
/*
|
||||
* 통합자료관관리시스템과 동일하게 게시글 저장 처리를 수행하며,
|
||||
* 제목의 경우, DB에 일부 특수문자에 대하여 치환되어 저장되고,
|
||||
* 내용의 경우, HTML 요청된 그대로 저장하되 표출할 때 HTML Sanitizing하여 표출토록 처리하기로 협의됨에 따라
|
||||
* 제목 설정시 치환되어 저장토록 함 (2021.12.21, 이규모차장님)
|
||||
*/
|
||||
this.title = StringUtil.getRemovedQuotesStr(title);
|
||||
}
|
||||
public String getContent() {
|
||||
return content;
|
||||
@ -287,6 +294,10 @@ public class ArticleVO extends PagingVO {
|
||||
return answer;
|
||||
}
|
||||
|
||||
public String getSanitizedAnswer() {
|
||||
return StringUtil.sanitizeHtml(answer);
|
||||
}
|
||||
|
||||
public void setAnswer(String answer) {
|
||||
this.answer = answer;
|
||||
}
|
||||
|
||||
@ -137,6 +137,12 @@ public class FaqController extends NlibCommonController {
|
||||
// 읽음처리 및 상세내용 조회
|
||||
ArticleVO articleVO = faqService.selectArticle(searchArticleVO);
|
||||
|
||||
// AJAX OUT에 XSS처리되지 않은 HTML 전송 차단위한 변경 처리
|
||||
if(articleVO != null) {
|
||||
articleVO.setAnswer(articleVO.getSanitizedAnswer());
|
||||
articleVO.setContent(articleVO.getSanitizedContent());
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// JSON변환 응답 처리
|
||||
//-------------------------------
|
||||
|
||||
@ -273,6 +273,45 @@ public class StringUtil extends StringUtils {
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글 제목 등 허용되지 말아야하는 일부 특수문자에 대한 치환 처리하여 리턴
|
||||
*
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public static String getRemovedQuotesStr(String val) {
|
||||
|
||||
if (isEmpty(val)) return val;
|
||||
|
||||
StringBuffer strBuff = new StringBuffer();
|
||||
for (int j = 0; j < val.length(); j++) {
|
||||
char c = val.charAt(j);
|
||||
switch (c) {
|
||||
case '<':
|
||||
strBuff.append("<");
|
||||
break;
|
||||
case '>':
|
||||
strBuff.append(">");
|
||||
break;
|
||||
case '&':
|
||||
strBuff.append("&");
|
||||
break;
|
||||
case '"':
|
||||
strBuff.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
strBuff.append("'");
|
||||
break;
|
||||
default:
|
||||
strBuff.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return strBuff.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 날짜 문자열(YYYYMMDD)을 받아서 화면 출력용 날짜 형식 문자열(YYYY-MM-DD)로 리턴한다.
|
||||
*
|
||||
@ -391,7 +430,9 @@ public class StringUtil extends StringUtils {
|
||||
* @param html
|
||||
* @return
|
||||
*/
|
||||
private static String sanitizeHtml(String html) {
|
||||
public static String sanitizeHtml(String html) {
|
||||
|
||||
if(isEmpty(html)) return html;
|
||||
|
||||
PolicyFactory policy = new HtmlPolicyBuilder()
|
||||
.allowAttributes("src", "align", "title").onElements("img")
|
||||
|
||||
@ -342,7 +342,7 @@ function fn_downloadFile(attachFileId, fileSn) {
|
||||
<li class="wt-question">
|
||||
<div class="w-tit">내용 <span class="required">*</span></div>
|
||||
<div class="w-form">
|
||||
<textarea name="content" id="content" cols="80" rows="10" placeholder="질문하실 내용을 입력하세요." style="width:100%;min-width:260px;"><c:out value='${searchArticle.unescapedContent}' escapeXml='false' /></textarea>
|
||||
<textarea name="content" id="content" cols="80" rows="10" placeholder="질문하실 내용을 입력하세요." style="width:100%;min-width:260px;"><c:out value='${searchArticle.sanitizedContent}' escapeXml='false' /></textarea>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -121,7 +121,7 @@ function fn_downloadFile(attachFileId, fileSn) {
|
||||
<div class="view-body">
|
||||
<div class="view-con">
|
||||
<div class="view-txt">
|
||||
<c:out value='${article.content}' escapeXml='false' />
|
||||
<c:out value='${article.sanitizedContent}' escapeXml='false' />
|
||||
</div>
|
||||
</div>
|
||||
<ul class="attachments">
|
||||
|
||||
@ -145,7 +145,7 @@ function fn_downloadFile(attachFileId, fileSn) {
|
||||
<div class="view-con">
|
||||
<div class="view-txt">
|
||||
<p>
|
||||
<c:out value='${article.unescapedContent}' escapeXml="false" />
|
||||
<c:out value='${article.sanitizedContent}' escapeXml='false' />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -156,7 +156,7 @@ function fn_downloadFile(attachFileId, fileSn) {
|
||||
<span class="right"><c:out value='${article.modDd }'/></span>
|
||||
</div>
|
||||
<div class="answer-con">
|
||||
<p><c:out value='${article.answer}' escapeXml = 'false' /></p>
|
||||
<p><c:out value='${article.sanitizedAnswer}' escapeXml = 'false' /></p>
|
||||
</div>
|
||||
</div>
|
||||
</c:if>
|
||||
|
||||
@ -62,6 +62,9 @@ $( document ).ready(function() {
|
||||
|
||||
var $qObj = $(qObj);
|
||||
if($qObj.hasClass('on')) {
|
||||
$qObj.removeClass("on");
|
||||
$qObj.next(".answer").stop().slideUp(300);
|
||||
$qObj.next(".answer").html("");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
<url-pattern>*.do</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- 별도 OWASP HTML Sanitizer 사용으로 대체 -->
|
||||
<!--
|
||||
<filter>
|
||||
<filter-name>HTMLTagFilter</filter-name>
|
||||
<filter-class>egovframework.rte.ptl.mvc.filter.HTMLTagFilter</filter-class>
|
||||
@ -28,6 +30,7 @@
|
||||
<filter-name>HTMLTagFilter</filter-name>
|
||||
<url-pattern>*.do</url-pattern>
|
||||
</filter-mapping>
|
||||
-->
|
||||
|
||||
<!-- Spring Security Filter : DIGITALSHIP 2021.07.02 -->
|
||||
<filter>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user