DAY 50

ChangWoo·2022년 11월 15일
0

중앙 HTA

목록 보기
3/51

오늘은 로그인과 로그아웃 기능에 대해 배우고 코딩해보는 시간을 가졌다.

로그인과 로그아웃

  • 인증된 사용자 정보를 서버의 HttpSession 객체에 저장하는 것

  • HttpSession 객체는 고유한 아이디를 가지고 있고, 그 세션과 관련있는 클라이언트도 같은 아이디를 가지고 있기 때문에,
    클라이언트마다 사용하는 세션객체가 고유하게 구별된다.

  • HttpSession 객체는 요청/응답이 완료되어도 사라지지 않고, 명시적으로 로그아웃하거나 일정시간 이상 해당 사이트를
    이용하지 않을 때 사라진다.
    따라서 HttpSession에 저장한 정보는 여러 JSP에서 이용할 수 있다.

로그인 로그아웃을 학습하기 전 테이블 생성 및 수정

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
);

-- SAMPLE_BOARDS 테이블의 BOARD_WRITER 컬럼에 외래키 제약조건을 추가한다.
-- SAMPLE_BOARDS 테이블의 BOARD_WRITER 컬럼의 값은 SAMPLE_BOARD_USERS 테이블의 USER_ID를 참조한다.
ALTER TABLE SAMPLE_BOARDS ADD CONSTRAINT BOARD_WRITER_FK
FOREIGN KEY (BOARD_WRITER) REFERENCES SAMPLE_BOARD_USERS (USER_ID);
-- SAMPLE_BOARD_REVIEWS 테이블의 REVIEW_WRITER 컬럼에 외래키 제약조건을 추가한다.
-- SAMPLE_BOARD_REVIEWS 테이블의 REVIEW_WRITER 컬럼의 값은 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);
public class User {
	
	private String id;
	private String password;
	private String name;
	private String email;
	private String deleted;
	private Date createdDate;
	private Date updatedDate;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getDeleted() {
		return deleted;
	}
	public void setDeleted(String deleted) {
		this.deleted = deleted;
	}
	public Date getCreatedDate() {
		return createdDate;
	}
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}
	public Date getUpdatedDate() {
		return updatedDate;
	}
	public void setUpdatedDate(Date updatedDate) {
		this.updatedDate = updatedDate;
	}
}

회원가입 기능 구현
(아이디, 이메일이 중복이 아닐 경우 유저 정보 등록하기)

users.xml	
    <!--  
		아이디를 전달받아서 sample_board_users 테이블에서 사용자정보를 조회해서 반환한다.
	-->
	<select id="getUserById" parameterClass="string" resultClass="com.sample.vo.User">
		select
			user_id as id,
			user_password as password,
			user_name as name,
			user_email as email,
			user_deleted as deleted,
			user_created_date as createdDate,
			user_updated_date as updatedDate
		from
			sample_board_users
		where
			user_id = #value#
	
	</select>
	<!--  
		이메일를 전달받아서 sample_board_users 테이블에서 사용자정보를 조회해서 반환한다.
	-->
	<select id="getUserByEmail" parameterClass="string" resultClass="com.sample.vo.User">
			select
			user_id as id,
			user_password as password,
			user_name as name,
			user_email as email,
			user_deleted as deleted,
			user_created_date as createdDate,
			user_updated_date as updatedDate
		from
			sample_board_users
		where
			user_email = #value#
	</select>
	<!--  
		사용자정보를 전달받아서 sample_board_users 테이블에서 저장한다.
	-->
	<insert id="insertUser" parameterClass="com.sample.vo.User">
		insert into sample_board_users
			(user_id, user_password, user_name, user_email)
		values
			(#id#, #password#, #name#, #email#)
	</insert>
public class UserDao {
	
	public User getUserById(String id) {
		return (User) SqlMapper.selectOne("getUserById", id);
	}
	
	public User getUserByEmail(String email) {
		return (User) SqlMapper.selectOne("getUserByEmail", email);
	}
	
	public void insertUser(User user) {
		SqlMapper.insert("insertUser", user);
	}
}
register.jsp
<%
	// 회원가입 폼에서 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을 응답으로 보낸다.
	User savedUser = userDao.getUserById(id);
	if (savedUser != null) {
		response.sendRedirect("form.jsp?error=invalid");
		return;
	}
	
	// 이메일로 사용자정보를 조회한다. 사용자정보가 null이 아니면 form.jsp를 재요청하는 URL을 응답으로 보낸다.
	savedUser = userDao.getUserByEmail(email);
	if (savedUser != null) {
		response.sendRedirect("form.jsp?error=invalid");
		return;
	}
	
	// insertUser(user)를 실행해서 사용자정보를 데이터베이스 저장시킨다.
	userDao.insertUser(user);
	
	// 재요청 URL을 응답으로 보낸다
	response.sendRedirect("completed.jsp");
%>
form.jsp

<%
	// 회원가입 실패로 form.jsp?error=invalid로 재요청했을 때 errorCode의 값은 invalid다. 
		String errorCode = request.getParameter("error");
		
%>
	
	<p>아이디, 비밀번호, 이름, 이메일을 입력해서 회원가입을 신청하세요</p>
	
<%
	if ("invalid".equals(errorCode)){
%>
	<div class="alert alert-danger">
		<strong>회원가입 오류</strong> 아이디 혹은 이메일이 이미 사용중입니다.
	</div>
<%
	}
%>

중복된 아이디 혹은 이메일로 회원가입을 하였을 경우

정상적으로 회원가입이 완료된 경우

로그인 기능 구현
(가입된 아이디가 있고 비밀번호와 일치할 때 로그인되는 기능)


login.jsp

<%
	// 로그인폼에서 화면에서 login.jsp를 실행 요청할 때 제출한 폼 입력값을 요청객체에서 조회한다.
	String id = request.getParameter("id");
	String password = request.getParameter("password");
	
	// 사용자 정보 조회를 위해서 UserDao 객체를 생성한다.
	UserDao userDao = new UserDao();
	
	// 아이디로 사용자 정보를 조회해서 사용자정보가 null이면 가입된 아이디가 아니므로 로그인화면을 재요청하는 URL을 응답으로 보낸다.
	 User savedUser = userDao.getUserById(id);
	if (savedUser == null) {
		response.sendRedirect("loginform.jsp?error=fail");
		return;
	}
	
	// 조회된 사용자정보의 비밀번호와 입력한 비밀번호가 일치하지 않으면 로그인화면을 재요청하는 URL을 응답으로 보낸다.
	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");
%>
loginform.jsp

<%
		// 회원가입 실패로 form.jsp?error=invalid로 재요청했을 때 errorCode의 값은 invalid다. 
		String errorCode = request.getParameter("error");
	%>
	<p>아이디, 비밀번호 입력해서 로그인하세요</p>
	<%
		if ("fail".equals(errorCode)){
	%>
	<div class="alert alert-danger">
		<strong>로그인 오류</strong> 아이디 혹은 비밀번호를 확인하세요.
	</div>
	<%
		}
	%>
header.jsp
<%
 	User user = (User) session.getAttribute("loginedUser");
%>
<%
	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>
<%
	}
%>

아이디 혹은 비밀번호가 일치하지 않는 경우

정상적으로 로그인 된 경우

로그아웃 기능 구현
(session.invalidate() 메소드로 세션객체를 무효화시키기)

logout.jsp

<%
	// 로그아웃은 기존 세션객체를 무효화시킨다.
	session.invalidate();

	// 재요청 URL을 응답으로 보낸다.
	response.sendRedirect("../home.jsp");
%>

익명 게시판을 게시판으로 변경
(로그인한 사용자만 게시글 등록하기)

  • 로그인 한 상태에서만 새 글 등록이란 메뉴가 나타나도록 하기
list.jsp

	<%
		// HttpSession 객체에 저장된 인증된 사용자 정보를 조회한다.
		User user = (User) session.getAttribute("loginedUser");
		// 인증된 사용자 정보가 존재하면, 새글 등록 링크를 출력한다.
		if (user != null) {
	%>
		<a href="form.jsp" class="btn btn-primary btn-sm float-end">새 글 등록</a>
	<%
		}
	%>

로그인을 하지 않은 상태에서는 "새 글 등록" 버튼이 비활성화된다.

로그인 한 상태에서는 "새 글 등록" 버튼이 활성화된다.

만약, 로그인을 한 상태에서 새 글 등록을 들어갔을 때,
그 주소를 복사한 후 붙여놓으면 접속이 가능하기 때문에 form.jsp에서도 인증된 사용자 정보를 확인하고 null이면
로그인 폼으로 돌아가도록 해야한다.

form.jsp

 <%
	// HttpSession 객체에 저장된 인증된 사용자 정보를 조회한다.
	User user = (User) session.getAttribute("loginedUser");
	// 인증된 사용자 정보가 존재하지 않으면, 로그인 폼을 재요청하게 한다.
	if (user == null) {
		response.sendRedirect("../user/loginform.jsp?error=deny");
		return;
	}
 %>
loginform.jsp

	<%
		// 회원가입 실패로 form.jsp?error=invalid로 재요청했을 때 errorCode의 값은 invalid다. 
		String errorCode = request.getParameter("error");		
	%>
	<p>아이디, 비밀번호 입력해서 로그인하세요</p>
	<%
		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>
	<%
		}	
	%>

글 수정/삭제 기능 수정
(작성한 아이디로만 삭제 및 수정이 가능하도록 하기)

detail.jsp

<%
	// 인증된 사용자 정보를 조회한다.
	User user = (User) session.getAttribute("loginedUser");
%>

<%
    // 인증된(로그인된) 사용자 정보가 존재하고, 
    // 로그인한 사용자의 아이디와 게시글 작성자의 아이디가 일치하는 경우 삭제/수정 링크 출력 
	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>
<%
	}
%>

작성자가 hong인 게시글을 다른 유저는 수정/삭제가 불가능하다.

글을 작성한 유저만 글을 삭제/수정이 가능하다.

링크만 숨기는 것이 아닌 로그인한 사용자의 아이디와 게시글 작성자의 아이디가 서로 다르면 게시글을 수정/삭제할 수 없도록 하기.

delete.jsp

<%
	// 인증된 사용자 정보를 조회한다.
	User user = (User) session.getAttribute("loginedUser");

	// 로그인한 사용자의 아이디와 게시글 작성자의 아이디가 서로 다르면 게시글을 삭제할 수 없다. 
	// detail.jsp를 재요청하는 URL을 응답으로 보낸다.
	if (!user.getId().equals(board.getWriter())) {
		response.sendRedirect("detail.jsp?no=" + boardNo + "&error=deny");
		return;
	}
%>
detail.jsp / update.jsp

<%
		String errorCode = request.getParameter("error");
	%>
	
	<%
		if ("deny".equals(errorCode)) {
	%>
		<div class="alert alert-danger">
			<strong>수정/삭제 거부</strong>다른 사용자가 작성한 게시글은 수정/삭제할 수 없습니다.
		</div>
	<%
		}
	%>

홍길동이 작성한 글은 김유신이 링크로 직접 들어간다하더라도 수정/삭제를 할 수 없다.

profile
한 걸음 한 걸음 나아가는 개발자

0개의 댓글