[C-3-5] 게시물 작성 시 스프링 시큐리티 처리

2020. 1. 22. 15:40Project C (SBMS)/Project C 파트3

반응형

스프링 시큐리티를 사용할 때 POST 방식의 전송은 반드시 CSRF 토큰을 사용하도록 추가해야한다.

따라서, 게시글의 작성 기능에는 CSRF 토큰 사용은 필수이다.

 

수정 / 삭제에는 현재 로그인한 사용자와 게시글 작성자가 일치해야하는 경우에만 가능하게 해야한다.

과거에는 인터셉터로 처리했지만, @PreAuthorize 의 경우에는 표현식으로 처리가능하다.


views/board

list.jsp

 

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

	<%@ include file="../includes/header.jsp"%>	
	<div class="review-form" style="width: 200px;border: 1px solid black; background:#D9E5FF; text-align:center; position: fixed;">
	<form>
	
		<input type='hidden' id='bookNum' name='bookNum' />
		<input type='hidden' id='userId' name='${user_id }' />
		
		
		<h4>개인독서노트</h4>
		
	    <div class="form-group" >
	      <label  class="col-form-label col-form-label-sm" for="exampleSelect1">책장 종류</label>
	      <select class="form-control form-control-sm" id="shelfName" required="required">
					<option value="">책장선택</option>
					<option value="IT">IT</option>
					<option value="외국어">외국어</option>
					<option value="소설">소설</option>
					<option value="교육">교육</option>
	      </select>
	    </div>
	
		<div class="form-group">
		  <label class="col-form-label col-form-label-sm" for="inputSmall">책 이름</label>
		  <input class="form-control form-control-sm" type="text"  placeholder="책 이름을 입력해주세요." id="bookTitle" required="required">
		</div>
		<div class="form-group">
		  <label class="col-form-label col-form-label-sm" for="inputSmall">책 저자</label>
		  <input class="form-control form-control-sm" type="text" placeholder="책 저자 입력해주세요." id="writer" required="required">
		</div>
		<div class="form-group">
		  <label class="col-form-label col-form-label-sm" for="inputSmall">출판사</label>
		  <input class="form-control form-control-sm" type="text" placeholder="출판사를 입력해주세요." id="publisher" required="required">
		</div>
		<div class="form-group">
			<label class="col-form-label col-form-label-sm" for="inputDefault">구매날짜</label> 
			<input type="date" class="form-control form-control-sm" placeholder="구매날짜를 선택해주세요." id="purchaseDate" required="required">
		</div>
		<div class="form-group">
		  <label class="col-form-label col-form-label-sm" for="inputSmall">책 가격</label>
		  <input class="form-control form-control-sm" type="number" placeholder="책 가격을 입력해주세요." id="price" required="required">
		</div>
		<div class="form-group">
			<label class="col-form-label col-form-label-sm" for="inputSmall">독서 평</label>
			<textarea class="form-control form-control-sm" id="bookReview" rows="3" required="required"></textarea>
		</div>
		<div class="form-group">
			
			<input type="submit" class="btn btn-primary" id="btnReg"  value="독서평 등록"/>
			
			<button type="button" class="btn btn-danger" id="btnCan" onClick="cancelBookInfo();">취소</button>
		</div>
		
		<br/>
		</form>
	</div>
	<div style="left:201px;  width:1318px; position: absolute; " > 

		<h4>내 독서 노트</h4>
		
		<div align="right">
			<select id="search-shelf" name="type" style="width: 100px;">
				<option value="" selected="selected">전체 책장</option>
				<option value="IT">IT</option>
				<option value="외국어">외국어</option>
				<option value="소설">소설</option>
				<option value="교육">교육</option>
			</select>
			<button type="button" class="btn btn-primary" id="btn-search">검색</button>
		</div>
		
		<table class="table table-hover myBookList" >
			<!-- 			<thead>
			<tr>
		      <th scope="row">책장명</th>
		      <th scope="row">책이름</th>
		      <th scope="row">저자</th>
		      <th scope="row">출판사</th>
		      <th scope="row">구매날짜</th>
		      <th scope="row">책가격</th>
		      <th scope="row">독서평</th>
		      <th scope="row">삭제</th>
		    </tr> 
			</thead>
		  <tbody>
		   <tr>
		      <th scope="row">IT</th>
		      <td>자바 웹 프로그래밍</td>
		      <td>미노쿠마</td>
		      <td>미노북스</td>
		      <td>2020-01-11</td>
		      <td>35000</td>
		      <td>실습할 수 있어서 아주 좋다.</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr> 
		    
 		    <tr class="table-primary">
		      <th scope="row">Primary</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-secondary">
		      <th scope="row">Secondary</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-success">
		      <th scope="row">Success</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-danger">
		      <th scope="row">Danger</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-warning">
		      <th scope="row">Warning</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-info">
		      <th scope="row">Info</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-light">
		      <th scope="row">Light</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr>
		    <tr class="table-dark">
		      <th scope="row">Dark</th>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>Column content</td>
		      <td>
		      	<button type="button" class="btn btn-outline-success">수정</button>
				<button type="button" class="btn btn-outline-info">삭제</button>
			  </td>
		    </tr> 
		     
		  </tbody>
		  -->
		</table>
		
		<script type="text/javascript">
		
		var loginId = null;
		
		<sec:authorize access="isAuthenticated()">
			loginId = '<sec:authentication property="principal.username"/>';
		</sec:authorize>
		
		var csrfHeaderName = "${_csrf.headerName}";
		var csrfTokenValue = "${_csrf.token}";
		
		//Ajax spring security header..
		$(document).ajaxSend(function(e, xhr, options){
			xhr.setRequestHeader(csrfHeaderName, csrfTokenValue);
		});
		
		var searchShelf = $("#search-shelf").val();
		
		/* 도서 목록 JSON 데이터 추출 */
			
			var thead = "";
			thead += "<thead>";
			thead += "<tr>";
			thead += "<th scope=\"col\" width=\"10px;\">책장명</th>";
			thead += "<th scope=\"col\" width=\"10px;\">책 이름</th>";
			thead += "<th scope=\"col\" width=\"10px;\">저자</th>";
			thead += "<th scope=\"col\" width=\"10px;\">출판사</th>";
			thead += "<th scope=\"col\" width=\"10px;\">구매날짜</th>";
			thead += "<th scope=\"col\" width=\"20px\">책 가격</th>";
			thead += "<th scope=\"col\" width=\"100px;\">독서평</th>";
			thead += "<th scope=\"col\" width=\"50px;\">수정 및 삭제</th>";
			thead += "</tr>";
			thead += "</thead>";
		
		
		var bookinfoUL = $(".myBookList");
		bookInfoService.getList({type: searchShelf},function(list) {
			
			var innerTable = "";
			innerTable += thead;
			for (var i = 0, len = list.length || 0; i < len; i++) {
	    		console.log(list[i]);
	    		innerTable += "<tr>";
	    		innerTable += "<th scope=\"row\">" + list[i].shelfName + "</th>";
	    		innerTable += "<td>" + list[i].bookTitle + "</td>";
	    		innerTable += "<td>" + list[i].writer + "</td>";
	    		innerTable += "<td>" + list[i].publisher + "</td>";
	    		innerTable += "<td>" + list[i].purchaseDate.substr(0,10) + "</td>";
	    		innerTable += "<td>" + list[i].price + "</td>";
	    		innerTable += "<td>" + list[i].bookReview + "</td>";
	    		if ( loginId === list[i].userId){
	    			innerTable += "<td><button class=\"btn btn-success\" type='button' onClick=\"editBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">수정</button><button class=\"btn btn-warning\" type='button' onClick=\"removeBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">삭제</button></td>";
	    		}else{
	    			//list[i].userId
	    			innerTable += "<td><button class=\"btn btn-primary disabled\" type=\"button\" onClick=\"editBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">수정/삭제 불가</button></td>";
	    				    			
	    		}
	    		innerTable += "</tr>";
	    	}
				bookinfoUL.html(innerTable);
			});
		
		/* 도서 등록 또는 수정 JSON 데이터 전송 */
		$("#btnReg").click(function() {
			
			/* 폼 유효성 검사 */
			if($("#shelfName").val() === "" || $("#bookTitle").val() === "" || $("#writer").val() === "" || $("#publisher").val() === "" || $("#purchaseDate").val() === "" || $("#price").val() === "" || $("#bookReview").val() === ""){
				alert("개인독서노트 폼을 빠짐없이 모두 작성해주세요.");
				return;
			}
			
			if($("#btnReg").val() === "독서평 등록"){
				bookInfoService.add(
						{ 
						  shelfName: $("#shelfName").val(),
						  userId: loginId,
						  bookTitle:$("#bookTitle").val(),
						  writer:$("#writer").val(),
						  publisher: $("#publisher").val(),
						  purchaseDate:$("#purchaseDate").val(),
						  price:$("#price").val(),
						  bookReview:$("#bookReview").val()
						},
						function(result){
							showList();
							alert("새 독서평이 등록되었습니다.");
							$("#btnReg").val("독서평 등록");
							$("#btnReg").attr('class','btn btn-primary');
							$("#bookNum").val(""),
							$("#userId").val(""),
							$("#bookTitle").val(""),
							$("#writer").val(""),
							$("#publisher").val(""),
							$("#purchaseDate").val(""),
							$("#price").val(""),
							$("#bookReview").val("")
							
						}
				);
			}else if($("#btnReg").val() === "독서평 수정"){
				bookInfoService.update(
						{ 
						  bookNum: $("#bookNum").val(),
						  shelfName: $("#shelfName").val(),
						  userId: $("#userId").val(),
						  bookTitle:$("#bookTitle").val(),
						  writer:$("#writer").val(),
						  publisher: $("#publisher").val(),
						  purchaseDate:$("#purchaseDate").val(),
						  price:$("#price").val(),
						  bookReview:$("#bookReview").val()
						  
						},
						function(result){
							showList();
							alert($("#bookNum").val() + "번의 독서평이 수정되었습니다.");
							$("#bookNum").val(""),
							$("#userId").val(""),
							$("#bookTitle").val(""),
							$("#writer").val(""),
							$("#publisher").val(""),
							$("#purchaseDate").val(""),
							$("#price").val(""),
							$("#bookReview").val("")
							$("#btnReg").val("독서평 등록");
							$("#btnReg").attr('class','btn btn-primary');
							
						}
				);
			}
		});
		
		/* 도서 항목 JSON 데이터 출력 갱신 */
		function showList() {
	
			var searchShelf = $("#search-shelf").val();
			var replyUL = $(".myBookList");
			var innerTable = "";
			
			bookInfoService.getList({type: searchShelf},function(list) {
			innerTable += thead;
			
			for (var i = 0, len = list.length || 0; i < len; i++) {
	    		console.log(list[i]);
	    		
	    		innerTable += "<tr>";	
	    		innerTable += "<th scope=\"row\">" + list[i].shelfName + "</th>";
	    		innerTable += "<td>" + list[i].bookTitle + "</td>";
	    		innerTable += "<td>" + list[i].writer + "</td>";
	    		innerTable += "<td>" + list[i].publisher + "</td>";
	    		innerTable += "<td>" + list[i].purchaseDate.substr(0,10) + "</td>";
	    		innerTable += "<td>" + list[i].price + "</td>";
	    		innerTable += "<td>" + list[i].bookReview + "</td>";
	    		if ( loginId === list[i].userId){
	    			innerTable += "<td><button class=\"btn btn-success\" type='button' onClick=\"editBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">수정</button><button class=\"btn btn-warning\" type='button' onClick=\"removeBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">삭제</button></td>";	
	    		}else{
	    			//list[i].userId
	    			innerTable += "<td><button class=\"btn btn-primary disabled\" type=\"button\" onClick=\"editBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">수정/삭제 불가</button></td>";
	    		}
	    		
	      		innerTable += "</tr>";
	    	}
				bookinfoUL.html(innerTable);
			});
		}
		
		/* 도서 등록 폼 초기화 */
		function cancelBookInfo(){
			$("#shelfName").val("");
			$("#btnReg").val("독서평 등록");
			$("#btnReg").attr('class','btn btn-primary');
			$("#bookNum").val(""),
			$("#userId").val(""),
			$("#bookTitle").val(""),
			$("#writer").val(""),
			$("#publisher").val(""),
			$("#purchaseDate").val(""),
			$("#price").val(""),
			$("#bookReview").val(""),
			$(".review-form").css("background-color", '#D9E5FF');
		}
		
		/* 도서 수정 폼 (도서 등록 폼 불러오기) */
		function editBookInfo(bookNum, originUserId) {
			
		 	 if(loginId  != originUserId){
		 	   $(".review-form").css("background-color", '#D9E5FF');
		 	   alert("자신이 작성한 댓글만 수정이 가능합니다. \n이 도서평은 " + originUserId + "님이 작성하였습니다.");
		 	   cancelBookInfo();
		 	   return;
		 	 }
		 	$(".review-form").css("background-color", '#CEFBC9');
		 	
			bookInfoService.get(bookNum, function(result){
				$("#shelfName").val(result.shelfName);
				$("#userId").val(result.userId);
				$("#bookTitle").val(result.bookTitle);
				$("#writer").val(result.writer);
				$("#publisher").val(result.publisher);
				$("#purchaseDate").val(result.purchaseDate.substr(0,10));
				$("#price").val(result.price);
				$("#bookReview").val(result.bookReview);
				$("#bookNum").val(result.bookNum);
				$("#btnReg").val("독서평 수정");
				$("#btnReg").attr('class','btn btn-success');
			});
		}
		
		/* 도서평 항목 삭제 */
		function removeBookInfo(bookNum, originUserId) {
				
	    	if(loginId != originUserId){
	     		alert("자신이 작성한 도서평만 삭제가 가능합니다.");
	     		return;
	     	}
			
			 
			if(confirm('정말 삭제하시겠습니까?')) { 
				bookInfoService.remove(bookNum, loginId, function(result){
		 	    	alert(bookNum + '번 도서평이 삭제되었습니다.');
		 	    	showList();
			 	});
			}
		}
		
		/* 도서평 항목 책장 분류 검색 */
		$(document).on('click', '#btn-search', function(){
			var searchShelf = $("#search-shelf").val();
			var bookinfoUL = $(".myBookList");
			var innerTable = "";
			
			bookInfoService.getList({type: searchShelf}, function(list) {
			
			innerTable += thead;
			
	    	for (var i = 0, len = list.length || 0; i < len; i++) {
	    		console.log(list[i]);
	    		innerTable += "<tr>";
	    		innerTable += "<th scope=\"row\">" + list[i].shelfName + "</th>";
	    		innerTable += "<td>" + list[i].bookTitle + "</td>";
	    		innerTable += "<td>" + list[i].writer + "</td>";
	    		innerTable += "<td>" + list[i].publisher + "</td>";
	    		innerTable += "<td>" + list[i].purchaseDate.substr(0,10) + "</td>";
	    		innerTable += "<td>" + list[i].price + "</td>";
	    		innerTable += "<td>" + list[i].bookReview + "</td>";
	    		if ( loginId === list[i].userId){
	    			innerTable += "<td><button class=\"btn btn-success\" type='button' onClick=\"editBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">수정</button><button class=\"btn btn-warning\" type='button' onClick=\"removeBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">삭제</button></td>";
	    		}else{
	    			//list[i].userId
	    			innerTable += "<td><button class=\"btn btn-primary disabled\" type=\"button\" onClick=\"editBookInfo('" + list[i].bookNum + "','" + list[i].userId + "')\">수정/삭제 불가</button></td>";
	    		}
	    		
	    		innerTable += "</tr>";
	    	}
	    		bookinfoUL.html(innerTable);
			});			

		});
		</script>
	</div>
</html>


 


resources/js

book-info.js

 

더보기
console.log("bookInfo Module........");
 
var bookInfoService = (function() {

	function getList(param, callback, error) {
		
		var searchShelf = param.type;
		
	     $.getJSON("/sbms/bookinfo/getList/" + searchShelf + ".json",
	        function(data) {
	          if (callback) {
	            callback(data);
	          }
	        }).fail(function(xhr, status, err) {
		      if (error) {
		        error();
		      }
	        });
	}
	
	function add(bookinfo, callback, error) {
		console.log("도서 정보를 추가합니다.");
		$.ajax({
			type : 'post',
			url : '/sbms/bookinfo/new',
			data : JSON.stringify(bookinfo),
			contentType : "application/json; charset=utf-8",
			success : function(result, status, xhr) {
				if (callback) {
					callback(result);
				}
			},
			error : function(xhr, status, er) {
				if (error) {
					error(er);
				}
			}
		})
	}
	
	function get(bookNum, callback, error) {
		$.get("/sbms/bookinfo/" + bookNum + ".json", function(result) {
			if (callback) {
				callback(result);
			}

		}).fail(function(xhr, status, err) {
			if (error) {
				error();
			}
		});
	}
	
	function update(bookinfo, callback, error) {
		$.ajax({
			type : 'put',
			url : '/sbms/bookinfo/' + bookinfo.bookNum,
			data : JSON.stringify(bookinfo),
			contentType : "application/json; charset=utf-8",
			success : function(result, status, xhr) {
				//alert('수정 reply!!!! 일단 성공!!');
				if (callback) {
					callback(result);
				}
			},
			error : function(xhr, status, er) {
				//alert('수정 reply!!!! 에러남!! ㅠㅠㅠㅠ');
				if (error) {
					error(er);
				}
			}
		});
	}
	
	function remove(bookNum, loginId, callback, error) {
		$.ajax({
		      type : 'delete',
		      url : '/sbms/bookinfo/' + bookNum,
		      data:  JSON.stringify({bookNum:bookNum, userId:loginId}),
		      contentType: "application/json; charset=utf-8",
		      
		      success : function(deleteResult, status, xhr) {
		        if (callback) {
		          callback(deleteResult);
		        }
		      },
		      error : function(xhr, status, er) {
		        if (error) {
		          error(er);
		        }
		      }
		});
	}
	
	return {
		getList : getList,
		add : add,
		get : get,
		update : update,
		remove : remove
	};
})();

 


src/main/java

com.sbms.controller

BookInfoController.java

 

더보기
package com.sbms.controller;

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.sbms.domain.BookVO;
import com.sbms.domain.Criteria;
import com.sbms.service.BookInfoService;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@RequestMapping("/bookinfo/")
@RestController
@Log4j
@AllArgsConstructor
public class BookInfoController {
	
	private BookInfoService bookInfoService;
	
	@GetMapping(value = "/getList/{shelfName}", produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE })
	public ResponseEntity<List<BookVO>> getList(@PathVariable String shelfName) {
		log.info("[http://localhost/sbms/bookinfo/getList/{shelfName}.json]");
		
		Criteria cri = new Criteria();
		cri.setShelfName(shelfName);
		
		return new ResponseEntity<>(bookInfoService.getList(cri), HttpStatus.OK);
	}
	@PreAuthorize("isAuthenticated()")
	@PostMapping(value = "/new", consumes = "application/json", produces = { MediaType.TEXT_PLAIN_VALUE })
	public ResponseEntity<String> create(@RequestBody BookVO book) {
		int insertCount = bookInfoService.register(book);
		return new ResponseEntity<>("success", HttpStatus.OK);
	}
	
	@GetMapping(value = "/{bookNum}", produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE })
	public ResponseEntity<BookVO> get(@PathVariable("bookNum") Long bookNum) {

		log.info("bookNum : " + bookNum);

		return new ResponseEntity<>(bookInfoService.get(bookNum), HttpStatus.OK);
	}
	@PreAuthorize("principal.username == #book.userId")
	@RequestMapping(method = { RequestMethod.PUT, RequestMethod.PATCH }, value = "/{bookNum}", consumes = "application/json", produces = {
					MediaType.TEXT_PLAIN_VALUE })
	public ResponseEntity<String> modify(@RequestBody BookVO book, @PathVariable("bookNum") Long bookNum) {

		book.setBookNum(bookNum);

		return bookInfoService.modify(book) == 1 ? new ResponseEntity<>("success", HttpStatus.OK)
				: new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);

	}
	
	@PreAuthorize("isAuthenticated()")
	@DeleteMapping(value = "/{bookNum}", produces = { MediaType.TEXT_PLAIN_VALUE })
	public ResponseEntity<String> remove(@RequestBody BookVO book, @PathVariable("bookNum") Long bookNum) {

		return bookInfoService.remove(bookNum) == 1 ? new ResponseEntity<>("success", HttpStatus.OK)
				: new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);

	}
	
}

 


 

수정사항

 

헤더의 로그인 영역에 로그인된 아이디 표기

 

수정 및 삭제 버튼 디자인 수정

- 수정 버튼 클릭 시 개인 독서노트 등록 폼 배경색상 변경

 

수정 및 삭제 버튼 기능 추가

- 로그인한 유저 아이디와 독서평을 등록했을 당시의 유저아이디비교해서 일치

 

수정/삭제 불가 버튼 추가

- 로그인한 유저 아이디와 독서평을 등록했을 당시의 유저아이디 비교해서 불일치

 

버튼 클릭 시 사유 표시

 

 

 

독서평 등록 폼 화면

 


독서평 수정 폼 화면


 

수정/삭제 불가 버튼 클릭 시의 화면

 

반응형