일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- jquery
- Vue
- 생성
- 방법
- kotlin
- IntelliJ
- aws
- Git
- 오라클
- Java
- db
- Eclipse
- 에러
- 스프링
- error
- JPA
- 코틀린
- 쿼리
- 넥사크로
- 프로그래머스
- 알고리즘
- GitHub
- mybatis
- Security
- JavaScript
- 시큐리티
- 함수
- Spring
- 자바
- oracle
- Today
- Total
송민준의 개발노트
썸머노트(summernote) 사용하기(스프링, 404에러 해결), XSS관련 본문
https://summernote.org/getting-started/#run-summernote
1. 위 썸머노트 페이지로 이동 해서 부트스트랩 4 버전으로 cdn을 받는다.(부 4 기준)
기본적으로 썸머노트는 부트스트랩과 제이쿼리 기반으로 만들어진거기 때문에(아닌 것도 있음) 밑에 코드 위에 불러오는게 있어야 한다. 밑에 KR은 한글 문제를 해결해줄것이다.
<!-- include summernote css/js -->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.js"></script>
<script src="https://github.com/summernote/summernote/tree/master/lang/summernote-ko-KR.js"></script>
2. 썸머노트는 div와 form에 적용이 가능한데 form에 쓰는 것을 권장하며 post 방식을 쓰는 것을 권장한다.
<form method="post">
<textarea id="summernote" name="editordata"></textarea>
</form>
<div id="summernote">Hello Summernote</div>
3. javascript에 추가
$(document).ready(function() {
$('#summernote').summernote();
});
4. 다음과 같이 속성 도 변경 가능하다.
<script>
$('#summernote').summernote({
placeholder: 'Hello Bootstrap 4',
tabsize: 2,
height: 100,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['view', ['fullscreen', 'codeview', 'help']]
]
});
</script>
5. 이대로 막 적으면 submit을 해도 잘 되긴 한다. 다만 image업로드를 하면 에러가 발생한다. 이에 썸머노트에서 제공하는 callback 함수를 이용하여 ajax로 서버에 이미지를 전송하도록 하겠다.
1) form 안에 textarea 선언
<div class="form-group">
<label for="board_content">내용</label>
<textarea name="BOARD_CONTENT" id="board_content"></textarea>
</div>
2) script 추가
function sendFile(file, el) {
var form_data = new FormData();
form_data.append('file', file);
$.ajax({
data: form_data,
type : "post",
url: 'summer_image',
cache :false,
contentType : false,
enctype : 'multipart/form-data',
processData : false,
success : function(img_name) {
$(el).summernote('editor.insertImage', img_name);
}
});
}
$(function() {
$('#board_content').summernote({
placeholder: '최대 500자 작성 가능합니다.',
height: 300,
lang: 'ko-KR',
callbacks: {
onImageUpload: function(files, editor, welEditable) {
for(var i = files.length -1; i>=0; i--) {
sendFile(files[i], this);
}
}
}
});
});
3) controller ( out.pirntln 뒤에 있는 경로는 본인이 저장하는 경로에...)
@ResponseBody
@PostMapping("/summer_image")
public void summer_image(MultipartFile file, HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String file_name = file.getOriginalFilename();
String server_file_name = fileDBName(file_name, save_folder);
System.out.println("server file : " + server_file_name);
file.transferTo(new File(save_folder + server_file_name));
out.println("resources/upload"+server_file_name);
out.close();
}
private String fileDBName(String fileName, String saveFolder) {
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int date = c.get(Calendar.DATE);
String homedir = saveFolder + year + "-" + month + "-" + date;
System.out.println(homedir);
File path1 = new File(homedir);
if (!(path1.exists())) {
path1.mkdir();
}
Random r = new Random();
int random = r.nextInt(100000000);
int index = fileName.lastIndexOf(".");
String fileExtension = fileName.substring(index + 1);
System.out.println("fileExtension = " + fileExtension);
String refileName = "bbs" + year + month + date + random + "." + fileExtension;
System.out.println("refileName = " + refileName);
String fileDBName = "/" + year + "-" + month + "-" + date + "/" + refileName;
System.out.println("fileDBName = " + fileDBName);
return fileDBName;
}
이클립스에 환경에서 개발하다보면 저장하는게 실경로와 가상경로가 다르다. 두번을 저장하게 되는데 이때 시간적 딜레이가 생겨서 404에러가 뜬다.(경로의 이미지를 참조를 못함)
두번 저장하는게 아닌 참조하는 곳에만 저장하기 위해서
톰캣에 들어가서 server options - Serve modules without publicshing 을 체크해준다.
그럼 해결이 되는데
다른 방법으론... 좀 가라이긴 하는데 아래와 같이 setTimeout으로 시간 간격을 준다.
파일 생성이 완료되는데 대략 4초가 걸려서 4초를 주고 사용자에게 업로드중인걸 알리기위해
스피너를 사용했다. (좋은 방법 아님)
$.ajax({
data: form_data,
type : "post",
url: 'summer_image',
cache :false,
contentType : false,
enctype : 'multipart/form-data',
processData : false,
success : function(img_name) {
$(".spinner-border").css("display","inline-block");
setTimeout(function() {
$(".spinner-border").css("display","none");
$(el).summernote('editor.insertImage', img_name);
}, 4000);
}
});
* XSS 공격에 대해서 필터링을 하고 싶어서 이것저것 찾아보니 jsoup를 써서 하면 간편하다고 한다.
다만 현재 버전의 summernote는 XSS 필터링을 제공해주고 있다.
https://summernote.org/deep-dive/#xss-protection-for-codeview
위로 가보면 default로 whitelist 필터링이 설정되어 있고 태그는 false로 되어 있다.
커스텀도 가능한 것 같으니 다음에 필요하면 해보겠음
'웹 > Spring Framework' 카테고리의 다른 글
Mybatis Cause: java.lang.NumberFormatException: For input string: "Y" 에러 해결방법 (0) | 2020.04.14 |
---|---|
(Spring) XSS 필터 - jsoup (0) | 2020.01.16 |
(spring) recaptcha v2 구현하기 - localhost test (1) | 2020.01.11 |
(Spring) kakao 소셜 로그인(SSO, oauth) (0) | 2020.01.10 |
프로젝트 import 후 tomcat에 add 안될 때 (0) | 2020.01.09 |