수업내용/Web

[2022.11.15.화] 로그인 기능

주니어주니 2022. 11. 15. 19:12

 

 

1. 오라클 database에 sample_board_users 테이블 추가

 

CREATE TABLE SAMPLE_BOARD_USERS (
    USER_ID VARCHAR2(20) PRIMARY KEY,
    USER_PASSWORD VARCHAR2(20) NOT NULL,
    USER_NAME VARCHAR2(100) NOT NULL,
    USER_EMAIL VARCHAR2(255) UNIQUE,
    USER_DELETED CHAR(1) DEFAULT 'N',
    USER_CREATED_DATE DATE DEFAULT SYSDATE,
    USER_UPDATED_DATE DATE DEFAULT SYSDATE
);

 

boards 테이블의 board_writer를 users 테이블의 user_id와 외래키 연결

reviews 테이블의 review_writer를 users 테이블의 user_id와 외래키 연결

ALTER TABLE SAMPLE_BOARDS ADD CONSTRAINT BOARD_WRITER_FK
FOREIGN KEY (BOARD_WRITER) REFERENCES SAMPLE_BOARD_USERS (USER_ID);

ALTER TABLE SAMPLE_BOARD_REVIEWS ADD CONSTRAINT BOARD_REVIEW_WRITER_FK
FOREIGN KEY (REVIEW_WRITER) REFERENCES SAMPLE_BOARD_USERS (USER_ID);

 

 

 

 

2. User 객체, UserDao, userxml 등을 모두 생성 

 

 

 

 

3. 공통되는 헤더 부분을 따로 뺌

 

-> 맨위의 공통되는 바 부분을 common/header.jsp에 적음 

 

각 JSP (detail.jsp, form.jsp, list.jsp, modifyform.jsp, home.jsp) 의 헤더부분 변경

 

 

ex) home.jsp 

<%@page import="com.sample.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
</head>
<body>
<%-- common폴더의 header.jsp를 이 jsp페이지에 포함시킨다. --%>
<jsp:include page="common/header.jsp">
	<jsp:param name="menu" value="home"/>
</jsp:include>
<div class="container my-3">
	<div class="row mb-3">
        <div class="col">
            <div class="border p-3 bg-light">
                <h1 class="mb-4">샘플 애플리케이션 입니다.</h1>
                <p class="">익명 게시판, 회원가입, 로그인 기능을 지원합니다.</p>
            </div>
        </div>
    </div>
</div>
</body>
</html>

 

 

- home.jsp 

<jsp:param name="menu" value="home"/>     

 

- board폴더의

detail.jsp, form.jsp, list.jsp, modifyform.jsp에는 

<jsp:param name="menu" value="board"/>

 

 

- user폴더의

completed.jsp 

<jsp:param name="menu" value="register"/>

form.jsp

<jsp:param name="menu" value="register"/>

loginform.jsp

<jsp:param name="menu" value="login"/>

 

 

 

- header.jsp 

 

1) name에 담긴 value 값을 header.jsp 에서 받아서 menu변수에 저장 

2) 메뉴를 클릭할 때마다 활성화 효과 주기 

    - menu가 "home"이면 "홈"에 활성화

    - menu가 "board"면 "게시물"에 활성화 

 

<%
	/* 
		home, detail, list, modifyform 각 JSP에서 include할 때 각 JSP로부터 받은 이름이 "menu"인 것의 값 추출 
		<jsp:include page="common/header.jsp">
			<jsp:param name="menu" value="home"/>
		</jsp:include>
	*/
	String menu = request.getParameter("menu");
%>

 

<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
	<div class="container">
		<ul class="navbar-nav me-auto">
			<li class="nav-item"><a class="nav-link <%="home".equals(menu) ? "active bg-danger" : "" %>" href="/web-board/home.jsp">홈</a></li>
			<li class="nav-item"><a class="nav-link <%="board".equals(menu) ? "active bg-danger" : "" %>" href="/web-board/board/list.jsp">게시판</a></li>
		</ul>
	</div>
</nav>

 

 

 

4. 회원가입

 

 

 

- user / form.jsp  (회원가입 폼) 

 

* 회원가입 jsp에서 보낸 error 라는 이름의 값을 받아서 errorCode에 저장

 -> 전달받은 errorCode의 이름이 "invalid"이면 -> 존재하는 아이디, 이메일이 있다는 뜻 

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style type="text/css">
	textarea {
		resize: none;
	}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="register"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">회원가입 폼</h1>
	
	<%
		// register.jsp에서 회원가입 실패로 form.jsp?error=invalid로 재요청했을 때 errorCode에 "error"의 값인 invalid 저장
		String errorCode = request.getParameter("error");
	%>
	
	<p>아이디, 비밀번호, 이름, 이메일을 입력해서 회원가입을 신청하세요</p>
	
	<%
		if("invalid".equals(errorCode)){
	%>
		<div class="alert alert-danger">
			<strong>회원가입 오류</strong> 아이디 혹은 이메일이 이미 사용중입니다.
		</div>
	<%
		}
	%>
	
	<form class="bg-light border p-3" method="post" action="register.jsp">		<%-- 같은 폴더에 있는 register.jsp --%>
		<div class="mb-3">
			<label class="form-label">아이디</label>
			<input type="text" class="form-control" name="id" />
		</div>
		<div class="mb-3">
			<label class="form-label">비밀번호</label>
			<input type="password" class="form-control" name="password" />
		</div>
		<div class="mb-3">
			<label class="form-label">이름</label>
			<input type="text" class="form-control" name="name" />
		</div>
		<div class="mb-3">
			<label class="form-label">이메일</label>
			<input type="text" class="form-control" name="email" />
		</div>
		<div class="text-end">
			<a href="../home.jsp" class="btn btn-secondary">취소</a>				<%-- 상위 폴더에 있는 home.jsp --%>
			<button type="submit" class="btn btn-primary">회원가입</button>
		</div>
	</form>
</div>
</body>
</html>

 

 

 

- user / register.jsp   (회원가입) 

 

* 아이디, 이메일이 null이 아니다 = 일치하는 아이디, 이메일이 있다 -> 이미 등록된 회원 -> 회원가입 오류 

   -> 회원가입폼에 오류페이지를 재요청 response.sendRedirect("form.jsp?error=invalid"); 

        (이름은 error, 값은 invalid인 것을 전달해줌) 

   -> return 반드시 붙임 !!! 

   -> 회원가입폼에서 전달받음 

 

<%@page import="com.sample.dao.UserDao"%>
<%@page import="com.sample.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 회원가입 폼에서 register.jsp를 실행요청할 때 제출한 폼 입력값을 요청객체에서 조회한다.
	String id = request.getParameter("id");
	String password = request.getParameter("password");
	String name = request.getParameter("name");
	String email = request.getParameter("email");
	
	// User객체를 생성해서 조회된 값을 저장한다.
	User user = new User();
	user.setId(id);
	user.setPassword(password);
	user.setName(name);
	user.setEmail(email);
	
	// UserDao 객체를 생성한다. 
	UserDao userDao = new UserDao();	
	
	// 아이디로 사용자정보를 조회한다. 사용자정보가 null이 아니면 form.jsp를 재요청하는 URL을 응답으로 보낸다. error라는 이름의 값이 invalid
	User savedUser = userDao.getUserById(id);
	if(savedUser != null){
		response.sendRedirect("form.jsp?error=invalid");
		return;
	}
	
	// 이메일로 사용자정보를 조회한다. 사용자정보가 null이 아니면 form.jsp를 재요청하는 URL을 응답으로 보낸다. error라는 이름의 값이 invalid
	savedUser = userDao.getUserByEmail(email);
	if(savedUser != null){
		response.sendRedirect("form.jsp?errer=invalid");
		return;
	}
	
	// insertUser(user)를 실행해서 데이터베이스에 저장시킨다. 
	userDao.insertUser(user);
	
	// 재요청 URL을 응답으로 보낸다.
	response.sendRedirect("completed.jsp");
	
%>

 

 

 

 

 

 

 

 

 

 

 


 

 

4. 로그인 

 

 

 

 

 

- user / loginform.jsp (로그인 폼) 

 

* 로그인 jsp에서 보낸 error 라는 이름의 값을 받아서 errorCode에 저장

 -> 전달받은 errorCode의 이름이 "fail"이면 -> 아이디가 없거나, 비밀번호가 틀리다는 뜻 

 

 

* 회원가입 안했는데 url에 직접적으로 board / form.jsp 또는 board / register.jsp를 입력해서 들어올 경우를 고려

-> form.jsp 와 register.jsp 에서 loginform.jsp?error=deny 요청

 -> 전달받은 errorCode의 이름이 "deny"이면 -> 로그인 필요 -> 로그인 폼 재요청

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style type="text/css">
	textarea {
		resize: none;
	}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="login"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">로그인 폼</h1>
	
	<p>아이디, 비밀번호 입력해서 로그인하세요</p>
	
	<%
		String errorCode = request.getParameter("error");
	
		if("fail".equals(errorCode)){
	%>
		<div class="alert alert-danger">
			<strong>로그인 실패</strong> 아이디 혹은 비밀번호가 일치하지 않습니다.
		</div>
	<%
		} else if ("deny".equals(errorCode)) {
	%>
		<div class="alert alert-danger">
			<strong>요청 거부</strong> 로그인이 필요한 접근입니다.
		</div>
	<%
		}
	%>
	
	<form class="bg-light border p-3" method="post" action="login.jsp">
		<div class="mb-3">
			<label class="form-label">아이디</label>
			<input type="text" class="form-control" name="id" />
		</div>
		<div class="mb-3">
			<label class="form-label">비밀번호</label>
			<input type="password" class="form-control" name="password" />
		</div>
		<div class="text-end">
			<button type="submit" class="btn btn-primary">로그인</button>
			<a href="form.jsp" class="btn btn-secondary">회원가입</a>
		</div>
	</form>
</div>
</body>
</html>

 

 

 

 

 

 

 

 

 

 

- user / login.jsp (로그인) 

 

* 로그인 폼에서 요청받은 값들을 받아서 변수에 저장 

-> 아이디에 해당하는 사용자정보 조회 

-> 사용자정보가 null이거나, 비밀번호가 일치하지 않으면 로그인 폼으로 error=fail 재요청 

-> 인증이 완료된 사용자정보를 "loginedUser"라는 이름으로 세션객체에 저장 

-> 세션아이디를 쿠키에 담아서 응답으로 보냄 

-> 브라우저를 껐다 켜도 유지 

-> 아예 다른 브라우저를 이용해야 세션객체가 새로 생김 ( 크롬/ 웨일 ) 

 

 

<%@page import="com.sample.vo.User"%>
<%@page import="com.sample.dao.UserDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 로그인 폼에서 login.jsp를 실행요청할 때 제출한 폼 입력값을 요청객체에서 조회한다.
	String id = request.getParameter("id");
	String password = request.getParameter("password");
	
	// UserDao 객체 생성 
	UserDao userDao = new UserDao(); 
	
	// 아이디로 사용자 정보를 조회해서 사용자정보가 null이면 가입된 아이디가 아니므로 로그인화면을 재요청하는 URL을 응답으로 보낸다. 
	// 조회된 사용자정보의 비밀번호와 입력한 비밀번호가 일치하지 않으면 로그인화면을 재요청하는 URL을 응답으로 보낸다. 
	User savedUser = userDao.getUserById(id);
	
	if(savedUser == null){
		response.sendRedirect("loginform.jsp?error=fail");
		return;
	}
	
	if(!savedUser.getPassword().equals(password)){
		response.sendRedirect("loginform.jsp?error=fail");
		return;
	}
	
	// 사용자 인증이 완료된 경우, 세션객체에 사용자정보를 저장한다. 
	// HttpSession의 setAttribute(String name, Object value) 메소드를 사용해서 세션객체에 사용자 정보를 저장한다. 
	session.setAttribute("loginedUser", savedUser);
	
	// 재요청 URL을 응답으로 보낸다.
	response.sendRedirect("../home.jsp");
%>

 

 

 

 

 

 

 

- logout.jsp (로그아웃) 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 로그아웃은 기존 세션객체를 무효화시킨다.
	session.invalidate();
	
	// 재요청 URL을 응답으로 보낸다.
	response.sendRedirect("../home.jsp");
%>

 

 

 


 

 

 

5. 로그인 후 글 작성, 수정, 삭제 -> 본인만 할 수 있도록 하기 

 

 

- home.jsp (홈화면) 요청

 

 

* 요청할 때마다 세션아이디 전달 

 

* 로그인.jsp에서 인증완료된 사용자 정보를 "logintedUser" 이름으로 세션 객체에 저장했음 

-> "loginedUser" 정보를 얻음 

 

* 등록된 사용자 정보가 아니면 ->  로그인, 회원가입 표시 

* 등록된 사용자 정보이면 -> 로그아웃만 표시 

 

<%@page import="com.sample.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	/* 
		home, detail, list, modifyform 각 JSP에서 include할 때 각 JSP로부터 받은 이름이 "menu"인 것의 값 추출 
		<jsp:include page="common/header.jsp">
			<jsp:param name="menu" value="home"/>
		</jsp:include>
	*/
	String menu = request.getParameter("menu");
	
	/*
		HttpSession 객체에 저장된 인증된 사용자 정보를 조회한다.
		login.jsp에서 인증이 완료된 사용자정보를 아래와 같이 HttpSession 객체에 저장했다.
		
		User savedUser = userDao.getUserById(id);
		session.setAttribute("loginedUser", savedUser); 
	*/
	User user = (User) session.getAttribute("loginedUser");
%>

<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
	<div class="container">
		<ul class="navbar-nav me-auto">
			<li class="nav-item"><a class="nav-link <%="home".equals(menu) ? "active bg-danger" : "" %>" href="/web-board/home.jsp">홈</a></li>
			<li class="nav-item"><a class="nav-link <%="board".equals(menu) ? "active bg-danger" : "" %>" href="/web-board/board/list.jsp">게시판</a></li>
		</ul>
<%
	if(user == null){
%>
		<ul class="navbar-nav">
			<li class="nav-item"><a class="nav-link <%="login".equals(menu) ? "active bg-danger" : "" %>" href="/web-board/user/loginform.jsp">로그인</a></li>
			<li class="nav-item"><a class="nav-link <%="register".equals(menu) ? "active bg-danger" : "" %>" href="/web-board/user/form.jsp">회원가입</a></li>
		</ul>
<%
	} else {
%>
		<span class="navbar-text"><strong class="text-white"><%=user.getName() %></strong>님 환영합니다.</span>
		<ul class="navbar-nav">
			<li class="nav-item"><a class="nav-link" href="/web-board/user/logout.jsp">로그아웃</a></li>
		</ul>
<% 		
	}
%>		
	</div>
</nav>

 

 

 

 

- list.jsp (게시물 목록) 요청

 

* 인증된 사용자 정보가 존재하면 -> 새글 등록 링크 출력 

 

 

<%@page import="com.sample.vo.User"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="com.sample.util.StringUtils"%>
<%@page import="com.sample.vo.Board"%>
<%@page import="java.util.List"%>
<%@page import="com.sample.dao.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="board"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">게시글 리스트</h1>
	<p>게시글 목록을 확인하세요. 
		<%
			// HttpSession 객체에 저장된 인증된 사용자 정보를 조회한다. 
			User user = (User) session.getAttribute("loginedUser");
			// 인증된 사용자 정보가 존재하면, 새글 등록 링크를 출력한다. 
			if(user != null){
		%>		
			<a href="form.jsp" class="btn btn-primary btn-sm float-end">새 글 등록</a>
		<%
			}
		%>
	</p>
	
	<%
		// < 최신순 10개씩 보이기 > 
		// 1. 한 페이지에 게시물 10개씩 보이기 결정 
		// 2. 현재 페이지 번호 조회
		// 3. 현재 페이지에 해당하는 게시물 범위 (1~10, 11~20)
		// 4. map에 조회범위 담기 ( pageNo가 begin과 end 사이 )
		// 5. 해당 범위의 게시물 조회하는 메소드 만들어서 담기

		int rows = 10;
		
		int currentPage = StringUtils.stringToInt(request.getParameter("page"),1);
		
		int begin = (currentPage-1)*rows + 1;
		int end = currentPage*rows;
		
		Map<String, Object> param = new HashMap<>();
		param.put("begin", begin);
		param.put("end", end);
		
		BoardDao boardDao = new BoardDao();
		List<Board> boardList = boardDao.getBoards(param);
	%>
	
	<table class="table">
		<thead>
			<tr>
				<th>번호</th>
				<th>제목</th>
				<th>작성자</th>
				<th>조회수</th>
				<th>등록일</th>
			</tr>
		</thead>
		<tbody>
		<%
			if(boardList.isEmpty()){
		%>
			<tr>
				<td colspan="5" class="text-center">등록된 게시글이 없습니다.</td>
			</tr>
		<%
			} else {
				for(Board board : boardList) {
		%>
			<tr>
				<td><%=board.getNo() %></td>
				<td><a href="detail.jsp?boardNo=<%=board.getNo() %>" class="text-decoration-none text-dark"><%=board.getTitle() %></a></td>
				<td><%=board.getWriter() %></td>
				<td><%=board.getReadCount() %></td>
				<td><%=StringUtils.dateToText(board.getCreatedDate()) %></td>
			</tr>
		<% 			
				}
			}
		
		%>
		</tbody>
	</table>
	<%
		// 1. 한 화면에 표시할 페이지 개수 결정 - 5개 (이전,1,2,3,4,5,다음)
		// 2. 전체 행 개수 조회 ( 메소드 )
		// 3. 전체 페이지 수 계산
		// 4. 총 페이지 블럭 개수
		// 5. 현재 페이지 블럭 계산 
		// 6. 페이지 블럭의 범위 
		
		int pages = 5;
		int totalRows = boardDao.getTotalRows();
		int totalPages = (int) Math.ceil((double)totalRows/rows);
		int totalPageBlocks = (int) Math.ceil((double)totalPages/pages); 
		int currentPageBlock = (int) Math.ceil((double)currentPage/pages);
		
		int beginPage = (currentPageBlock - 1)*pages + 1;
		int endPage = currentPageBlock == totalPageBlocks ? totalPages : currentPageBlock*pages ;
	%>
	
	<div aria-label="navigation">
		<ul class="pagination justify-content-center">
			<li class="page-item <%=currentPage<=1 ? "disabled" : ""%>">
				<a class="page-link" href="list.jsp?page=<%=currentPage - 1%>">이전</a>
			</li>
			<%
				for(int number=beginPage; number<=endPage; number++) {
			%>
			<li class="page-item <%=number == currentPage ? "active" : ""%>">
				<a class="page-link" href="list.jsp?page=<%=number%>"><%=number %></a>
			</li>
			<%
				} 
			%>
			<li class="page-item <%=currentPage >= totalPages ? "disabled" : ""%>">
				<a class="page-link" href="list.jsp?page=<%=currentPage + 1%>">다음</a>
			</li>
		</ul>
	</div>
</div>
</body>
</html>

 

 

 

- form.jsp (게시글 등록 폼 ) 요청

 

* (URL에 직접 입력하는 경우) 인증된 사용자 정보가 존재하지 않으면 -> 로그인 폼 재요청 

 

 

<%@page import="com.sample.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// HttpSession 객체에 저장된 인증된 사용자 정보를 조회한다. 
	User user = (User) session.getAttribute("loginedUser");
	// 인증된 사용자 정보가 존재하지 않으면, 로그인 폼을 재요청하게 한다.
	if(user == null){
		response.sendRedirect("../user/loginform.jsp?error=deny");
		return;
	}
%>	
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style type="text/css">
	textarea {
		resize: none;
	}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="board"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">게시글 등록폼</h1>
	
	<p>제목, 작성자, 내용을 입력해서 새 게시글을 등록하세요</p>
	<form class="bg-light border p-3" method="post" action="register.jsp">
		<div class="mb-3">
			<label class="form-label">제목</label>
			<input type="text" class="form-control" name="title" />
		</div>
		<div class="mb-3">
			<label class="form-label">내용</label>
			<textarea class="form-control" rows="6" name="content"></textarea>
		</div>
		<div class="text-end">
			<a href="list.jsp" class="btn btn-secondary">취소</a>
			<button type="submit" class="btn btn-primary">등록</button>
		</div>
	</form>
</div>
</body>
</html>

 

 

 

 

 

 

- register.jsp (게시글 등록 ) 요청 

 

* (URL에 직접 입력하는 경우) 인증된 사용자 정보가 존재하지 않으면 -> 로그인 폼 재요청 

 

* 작성자 -> 로그인한 사용자의 아이디 전달 

   => 작성자를 직접 전달받지 않는다 !   (세션객체에 들어있는 정보를 빼서 쓰는 것임 !!!) 

 

<%@page import="com.sample.vo.User"%>
<%@page import="com.sample.vo.Board"%>
<%@page import="com.sample.dao.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//HttpSession 객체에 저장된 인증된 사용자 정보를 조회한다. 
	User user = (User) session.getAttribute("loginedUser");
	// 인증된 사용자 정보가 존재하지 않으면, 로그인 폼을 재요청하게 한다.
	if(user == null){
		response.sendRedirect("../user/loginform.jsp?error=deny");
		return;
	}	

	String title = request.getParameter("title");
	String content = request.getParameter("content");
	
	Board board = new Board();
	board.setTitle(title);
	board.setWriter(user.getId());		// 작성자에 로그인한 사용자의 아이디를 넣는다. 
	board.setContent(content);
	
	BoardDao boardDao = new BoardDao();
	boardDao.insertBoard(board);
	
	response.sendRedirect("list.jsp");
%>

 

 

 

 

 

 

 

 

- delete.jsp (게시글 삭제) 요청 

 

* 인증된 사용자 정보가 존재하지 않으면 로그인폼 재요청

* 로그인한 사용자의 아이디와 게시글 작성자의 아이디가 다르면 게시글 삭제 불가 -> detail.jsp를 재요청 

 

<%@page import="com.sample.util.StringUtils"%>
<%@page import="com.sample.vo.User"%>
<%@page import="com.sample.vo.Board"%>
<%@page import="com.sample.dao.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 인증된 사용자 정보를 조회 -> 인증된 사용자정보가 존재하지 않으면 loginform.jsp를 재요청하는 응답을 보낸다. 
	User user = (User) session.getAttribute("loginedUser");
	if(user == null){
		response.sendRedirect("../user/loginform.jsp?error=deny");
		return;
	}

	// 게시글 정보를 삭제하세요. sample_boards의 board_delete를 'Y'으로 변경하세요
	int no = StringUtils.stringToInt(request.getParameter("no"));
	
	BoardDao boardDao = new BoardDao();
	Board board = boardDao.getBoardByNo(no);
	
	// 로그인한 사용자의 아이디와 게시글 작성자의 아이디가 다르면 게시글 삭제 불가
	// detail.jsp를 재요청하는 URL을 응답
	if(!user.getId().equals(board.getWriter())){
		response.sendRedirect("detail.jsp?boardNo=" + no + "&error=deny");
		return;
	}
	
	board.setDeleted("Y"); 
	
	boardDao.updateBoard(board);
	
	response.sendRedirect("list.jsp");
%>

 

 

 

 

 

 

 

- detail.jsp (상세정보) 요청

 

* 로그인한 정보가 작성자 정보와 다르면 -> 수정, 삭제 불가 

 

 

<%@page import="com.sample.vo.User"%>
<%@page import="com.sample.dao.ReviewDao"%>
<%@page import="com.sample.vo.Review"%>
<%@page import="java.util.List"%>
<%@page import="com.sample.util.StringUtils"%>
<%@page import="com.sample.vo.Board"%>
<%@page import="com.sample.dao.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>익명 게시판</title>
<style>
	textarea {
		resize: none;
	}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp">
	<jsp:param name="menu" value="board"/>
</jsp:include>
<div class="container my-3">
	<h1 class="mb-3 fs-4 border p-2 bg-light">게시글 상세정보</h1>
	
	<p>
		게시글 상세정보를 확인하세요
		<button type="button" class="btn btn-outline-dark btn-sm float-end" data-bs-toggle="modal" data-bs-target="#review-modal">리뷰쓰기</button>
	</p>
	
	<%
		String errorCode = request.getParameter("error");
		
		if("deny".equals(errorCode)){
	%>
			<div class="alert alert-danger">
				<strong>수정/삭제 불가</strong> 다른 사용자가 작성한 게시글은 수정/삭제할 수 없습니다.
			</div>
	<%
		} 
	%>
		
	<%
	
		// 인증된 사용자 정보를 조회한다.
		User user = (User) session.getAttribute("loginedUser");
		
		int no = StringUtils.stringToInt(request.getParameter("boardNo"));
		
		BoardDao boardDao = new BoardDao();
		Board board = boardDao.getBoardByNo(no);
		
		board.setReadCount(board.getReadCount() + 1);
		boardDao.updateBoard(board);
		
	%>
	
	<table class="table table-bordered">
		<tbody>
			<tr>
				<th>번호</th><td><%=board.getNo() %></td>
				<th>등록일</th><td><%=StringUtils.dateToText(board.getCreatedDate()) %></td>
			</tr>
			<tr>
				<th>제목</th><td><%=board.getTitle() %></td>
				<th>작성자</th><td><%=board.getWriter() %></td>
			</tr>
			<tr>
				<th>조회수</th><td><%=board.getReadCount() %></td>
				<th>리뷰갯수</th><td><%=board.getReviewCount() %></td>
			</tr>
			<tr>
				<th>내용</th>
				<td colspan="3"><textarea rows="6" class="form-control border-0" readonly="readonly"><%=board.getContent() %></textarea> </td>
			</tr>
		</tbody>
	</table>
	<div class="mb-3">
	<%
		// 인증된(로그인된) 사용자 정보가 존재하고, 인증된 사용자의 아이디와 게시물 작성자가 동일할 때만 삭제, 수정 가능 
		if(user != null && user.getId().equals(board.getWriter())) { 	
	%>
		<a href="delete.jsp?no=<%=board.getNo() %>" class="btn btn-danger">삭제</a>
		<a href="modifyform.jsp?no=<%=board.getNo() %>" class="btn btn-warning">수정</a>
	<%
		}
	%>	
		<a href="list.jsp" class="btn btn-outline-primary float-end">목록</a>
	</div>
	
	<!-- 
		게시글 리뷰 리스트 시작
	 -->
	 
	 <%
	 	ReviewDao reviewDao = new ReviewDao();
	 	List<Review> reviewList = reviewDao.getReviewsByBoardNo(board.getNo());
	 %>
	<ul class="list-group">

	 <% 
	 	if(reviewList.isEmpty()){
	 %>
 			<li class="list-group-item">
				<div class="row">
 					<div class="col-12" class="text-center">리뷰가 존재하지 않습니다. </div>
				</div>
			</li>
	 <% 
	 	} else { 
	 		for(Review review : reviewList){
	 %>
		
		<li class="list-group-item">
			<div class="row">
				<div class="col-12">
					<span class="fw-bold"><%=review.getWriter() %></span> <small class="float-end"><%=StringUtils.dateToText(review.getCreatedDate()) %> </small>
				</div>
				<div class="col-10"><%=review.getContent() %> </div>
				<div class="col-2 text-end">
					<a href="deleteReview.jsp?no=<%=review.getBoardNo() %>&rno=<%=review.getNo() %>" class="text-danger">
						<i class="bi bi-trash"></i>
					</a>
				</div>
			</div>
		</li>
		<%
		 		}
		 	} 
		%>
	</ul>
	</div>
	<!-- 
		게시글 리뷰 리스트 끝
	 -->
	
	<!-- 
		리뷰 등록폼이 포함된 모달창 시작
	 -->
	<div class="modal fade" id="review-modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
		<div class="modal-dialog">
			<form method="post" action="addReview.jsp">
				<!-- 
					이 리뷰가 몇번 게시글의 리뷰인지를 저장하기 위해서 hidden 필드에 이 게시글의 번호를 지정한다.
					이 입력폼을 서버로 제출하면 게시글번호(boardNo), 작성자(writer), 내용(content)이 전달된다.
				 -->
				<input type="hidden" name="boardNo" value="<%=board.getNo()%>">
				<div class="modal-content">
					<div class="modal-header py-2">
						<h1 class="modal-title fs-6" id="exampleModalLabel">리뷰 작성폼</h1>
						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
					</div>
					<div class="modal-body py-1">
						<!-- 
							작성자, 내용 입력요소를 확인하세요.
						 -->
						<div class="mb-3">
							<label class="form-label">작성자</label>
							<input type="text" class="form-control form-control-sm" name="writer" />
						</div>
						<div class="mb-3">
							<label class="form-label">내용</label>
							<textarea class="form-control" rows="3" name="content"></textarea>
						</div>
					</div>
					<div class="modal-footer">
						<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">닫기</button>
						<button type="submit" class="btn btn-primary btn-sm">리뷰등록</button>
					</div>
				</div>
			</form>
		</div>
	</div>
	<!-- 
		리뷰 등록폼이 포함된 모달창 끝
	 -->
</div>
</body>
</html>