DeseoDeSeo
[Spring] MVC07. 답글 작성, 게시글삭제, XSS대비 본문
get.jsp
로그인 되어있을 때만 답글 수정 가능하도록
<tr>
<td colspan="2" style="text-align:center;" >
<c:if test="${not empty mvo}">
<button data-btn="reply" class="btn btn-sm btn-primary">답글</button>
<button data-btn="modify" class="btn btn-sm btn-success">수정</button>
</c:if>
<c:if test="${empty mvo}">
<button disabled="disabled" class="btn btn-sm btn-primary">답글</button>
<button disabled="disabled" class="btn btn-sm btn-success">수정</button>
</c:if>
<button data-btn="list" class="btn btn-sm btn-warning">목록</button>
</td>
</tr>
modify.jsp
수정, 삭제는 해당 글의 작성자만 가능하도록
<tr>
<td colspan="2" style="text-align:center;" >
<c:if test="${not empty mvo && mvo.memID eq vo.memID }">
<button type="submit" class="btn btn-sm btn-primary">수정완료</button>
<button data-btn="remove" type="button" class="btn btn-sm btn-success">삭제</button>
</c:if>
<c:if test="${empty mvo or mvo.memID ne vo.memID }">
<button disabled="disabled" type="submit" class="btn btn-sm btn-primary">수정완료</button>
<button disabled="disabled" type="button" class="btn btn-sm btn-success">삭제</button>
</c:if>
<button data-btn="list" type="button" class="btn btn-sm btn-warning">목록</button>
<!-- cpath는 절대경로임. -->
</td>
</tr>
group은 내림차순, Sequence는 오름차순
BoardController.java
@PostMapping("/reply")
public String reply(Board vo) {
service.reply(vo);
return "redirect:/board/list";
}
reply.jsp
: 답글 작성하는 페이지
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix ="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix ="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="cpath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Spring MVC07</h2>
<div class="panel panel-default">
<div class="panel-heading">Board</div>
<div class="panel-body">
<form action="${cpath}/board/reply" method="post">
<input type="hidden" name="memID" value="${mvo.memID}">
<!-- 부모글의 게시글 번호 -->
<input type="hidden" name="idx" value="${vo.idx}">
<div class="form-group">
<label>제목</label>
<input value="<c:out value='${vo.title}'/>" type="text" name="title" class="form-control">
</div>
<div class="form-group">
<label>답변</label>
<textarea rows="10" cols="" name="content" class="form-control"></textarea>
</div>
<div class="form-group">
<label>작성자</label>
<input value="${mvo.memName}" readonly="readonly" type="text" name="writer" class="form-control">
</div>
<button type="submit" class="btn btn-default btn-sm">등록</button>
<button type="reset" class="btn btn-default btn-sm">취소</button>
<button data-btn="list" type="button" class="btn btn-default btn-sm">목록</button>
</form>
<form id="frm" method="get" action="">
<input id="idx" type="hidden" name="idx" value="${vo.idx}">
</form>
</div>
<div class="panel-footer">스프링게시판-뇽뇽이</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$("button").on("click",function(e){
var formData=$("#frm");
var btn =$(this).data("btn");
//버튼이 reply이면 action을 아래 경로로 바꿔줌.
if(btn=="list"){
formData.attr("action","${cpath}/board/list");
formData.find("#idx").remove();
//list는 idx가 필요 없으니까 찾아서 없애줌.
}
formData.submit();
}); //버튼 눌렀을 떄
});
</script>
</body>
</html>
BoardService.java
public void reply(Board vo);
BoardServiceImpl.java
@Override
public void reply(Board vo) {
// 답글 만들기
// vo :부모글의 번호, 로그인한 아이디, 제목, 답글, 작성자 이름
// 부모글의 정보를 가져오기
Board parent = mapper.read(vo.getIdx());
// 부모글의 boardGroup값을 답긆 vo에 저장하기.
vo.setBoardGroup(parent.getBoardGroup());
//sequence와 레벨은 부모글에서 +1
vo.setBoardSequence(parent.getBoardSequence()+1);
vo.setBoardLevel(parent.getBoardLevel()+1);
//현재 추가하려는 답글을 제외한 기존에 같은 그룹의 댓글 시퀀스 값을 1씩 올려줘야한다,
//왜냐면 최신순으로 답글이 출력되기 때문에.
mapper.replySeqUpdate(parent);
//답변 저장기능
mapper.replyInsert(vo);
}
BoardMapper.java
public void replySeqUpdate(Board parent);
BoardMapper.xml
<update id="replySeqUpdate" parameterType="kr.spring.entity.Board">
UPDATE TBLBOARD
SET BOARDSEQUENCE = BOARDSEQUENCE +1
WHERE BOARDGROUP = #{boardGroup}
AND BOARDSEQUENCE > #{boardSequence}
</update>
BoardMapper.java
public void replyInsert(Board vo);
BoardMapper.xml
: 답변 입력
<insert id="replyInsert" parameterType="kr.spring.entity.Board">
<!-- id,boardGroup만 가져와서 board타입에 넣고 before= 이전에 실행하겠다. -->
<selectKey keyProperty ="idx" resultType="kr.spring.entity.Board" order="BEFORE">
SELECT IFNULL(MAX(IDX)+1, 1) as idx
FROM TBLBOARD
</selectKey>
INSERT INTO TBLBOARD(IDX, MEMID, TITLE, CONTENT, WRITER, BOARDGROUP, BOARDSEQUENCE, BOARDLEVEL, BOARDAVAILABLE)
VALUES(#{idx},#{memID},#{title},#{content},#{writer},
#{boardGroup},#{boardSequence},#{boardLevel},1)
</insert>
BoardMapper.xml
: 게시글 가져오기
<select id="getList" resultType="kr.spring.entity.Board">
SELECT * FROM TBLBOARD
ORDER BY BOARDGROUP DESC, BOARDSEQUENCE ASC
</select>
list.jsp
: 이렇게 하면 답글에 들여쓰기가 된다.
<c:if test="${vo.boardLevel > 0 }">
<c:forEach begin="0" end="${vo.boardLevel}" step="1">
<span style="padding-left:15px"></span>
</c:forEach>
ㄴ[RE]
</c:if>
게시글 삭제하기
BoardMapper.xml
<update id="delete" parameterType="int">
UPDATE TBLBOARD
SET BOARDAVAILABLE=0
WHERE IDX=#{idx}
</update>
list.jsp
<c:if test="${vo.boardAvailable ==0}">
<a href="javascript:alert('삭제된 게시글 입니다. ')">
<c:if test="${vo.boardLevel > 0 }">
<c:forEach begin="0" end="${vo.boardLevel}" step="1">
<span style="padding-left:15px"></span>
</c:forEach>
ㄴ[RE]
</c:if>
삭제된 게시물 입니다.
</a>
</c:if>
<c:if test="${vo.boardAvailable > 0}">
<a href="${cpath}/board/get?idx=${vo.idx}">
<c:if test="${vo.boardLevel > 0 }">
<c:forEach begin="0" end="${vo.boardLevel}" step="1">
<span style="padding-left:15px"></span>
</c:forEach>
ㄴ[RE]
<!-- el(= ${vo.title} )식을 바로 사용하면 xss에 취약함. -->
</c:if>
<c:out value="${vo.title}"/>
</a>
</c:if>
XSS( Cross Site Scripting) 대비
: 게시글 작성할 때, 고의적으로 제목이나 내용에 스크립트를 넣어서 공격하는 기법에 대비
➜ jstl에 c:out을 사용.
list.jsp
이런식으로 작성한다.
<c:out value="${vo.title}"/>
modify.jsp
➜ 작성자가 작성할 수 있는 부분의 el식을 바꿔준다.
<tr>
<td>제목</td>
<td><input value="<c:out value='${vo.title}'/>" name="title" type="text" class="form-control"></td>
</tr>
<tr>
<td>내용</td>
<td>
<textarea class="form-control" name="content" rows="10" cols=""><c:out value="${vo.content}"/></textarea>
</td>
</tr>
get.jsp
<c:if test="${empty mvo}">
<button onclick="location.href='${cpath}/board/reply?idx=${vo.idx}'" class="btn btn-sm btn-primary">답글</button>
<button onclick="location.href='${cpath}/board/modify?idx=${vo.idx}' class="btn btn-sm btn-success">수정</button>
</c:if>
상단의 코드를 하단의 코드처럼 onclick의 location.href기능을 삭제한다. ( 코드가 길어져서 가독성이 떨어짐)
html5 중에서 요소를 구분하기 위한 data 속성 사용. (data- 옵션 뒤에 원하는 이름을 줄 수 있다.)
<c:if test="${not empty mvo}">
<button data-btn="reply" class="btn btn-sm btn-primary">답글</button>
<button data-btn="modify" class="btn btn-sm btn-success">수정</button>
</c:if>
<c:if test="${empty mvo}">
<button disabled="disabled" class="btn btn-sm btn-primary">답글</button>
<button disabled="disabled" class="btn btn-sm btn-success">수정</button>
</c:if>
아래의 코드는 페이지 이동을 위해서 idx값을 보내는 것.
</table>
<form id="frm" method="get" action="">
<input id="idx" type="hidden" name="idx" value="${vo.idx}">
</form>
<script type="text/javascript">
//10.11 링크처리(가독성, 보안(url노출 안됨.),유지보수 편리)//e:클릭했을 때, 요소를 감지하겠다.
$(document).ready(function(){
$("button").on("click",function(e){
var formData=$("#frm");
var btn =$(this).data("btn");
//버튼이 reply이면 action을 아래 경로로 바꿔줌.
if(btn=="reply"){
formData.attr("action","${cpath}/board/reply");
}else if(btn=="modify"){
formData.attr("action","${cpath}/board/modify");
}else if(btn=="list"){
formData.attr("action","${cpath}/board/list");
formData.find("#idx").remove();
//list는 idx가 필요 없으니까 찾아서 없애줌.
}
formData.submit();
}); //버튼 눌렀을 떄
});
</script>
'spring' 카테고리의 다른 글
[오류] Problems occurred while performing provisioning operation: operation plan must be resolved operation plan must be resolved (0) | 2023.11.01 |
---|---|
[Spring ] SpringMVC 08, 게시판 페이징 (1) | 2023.10.23 |
[Spring] mvc07 글 작성, 로그인, 로그아웃 (0) | 2023.10.21 |
[Spring] mvc07_환경설정, 3 tier구조 (1) | 2023.10.21 |
[Spring] mvc06, Security 로그아웃, 회원정보수정, 프로필 사진 변경 (1) | 2023.10.16 |