바트심슨으로 하루만 살고 싶다

[스프링 프레임워크]게시판 만들기 #5 : 로그인, 로그아웃, 정보수정 본문

Java/Spring

[스프링 프레임워크]게시판 만들기 #5 : 로그인, 로그아웃, 정보수정

바트심슨바게트 2023. 2. 16. 00:52

* 이전 내용

[스프링 프레임워크]게시판 만들기 #4 : 회원가입

 

[스프링 프레임워크]게시판 만들기 #3 : 데이터베이스 테이블 생성 및 게시판 카테고리 출력, 페

* 이전 내용 [스프링 프레임워크]게시판 만들기 #2 : Spring과 오라클 DB 연동 및 데이터 베이스 세팅, dependency 세팅 [스프링 프레임워크]게시판 만들기 #2 : Spring과 오라클 DB 연동 및 데이터 베이스

11027bart.tistory.com


로그인

아이디와 비밀번호 입력받아 로그인 하기.
기본적인 로그인 폼은 아래와 같다.

기본 로그인 폼

고려해야할 사항

1. 회원가입 시 modelAttribute로 주입한 객체와 다른 객체 사용
2. UserDTO 제약조건 설정 유지하기
3. 로그인 전 후 상단 메뉴바 변경하기
     - 로그인 전 ( 로그인, 회원가입 )  /    로그인 후 (정보수정, 로그아웃)
4. 로그인 후에만 접근할 수 있도록 설정

login.jsp

<form:form action="${root }user/login_pro" method="post" modelAttribute="tmpLoginBean">
	<div class="form-group">
		<form:label path="user_id">아이디</form:label>
		<form:input path="user_id" class="form-control" />
		<form:errors path="user_id" style="color:red" />
	</div>
	<div class="form-group">
		<form:label path="user_pw">비밀번호</form:label>
		<form:password path="user_pw" class="form-control" />
		<form:errors path="user_pw" style="color:red" />
	</div>
	<div class="form-group text-right">
		<form:button class="btn btn-primary" >로그인</form:button>
		<a href="${root }user/join" class="btn btn-danger">회원가입</a>
	</div>
</form:form>

Form 커스텀 태그를 이용해 아이디, 비밀번호 입력값을 받아 modelAttribute로 "tmpLoginBean"인 이름을 지정해주어 contextPath/user/login_pro로 아이디와 비밀번호를 담아 보낸다.


RootAppContext (로그인 정보 세션에 저장)

로그인 정보를 세션에 담기 위해 @Bean("loginBean"), @SessionScope를 이용해 User빈을 Session영역에 저장한다.
로그인 여부에 따라 기능에 차이를 두기 위함

package co.ky.sol.config;

@Configuration
public class RootAppContext {
	
	//로그인 기능을 위해 SessionScope로 Bean등록
	@Bean("loginBean")
	@SessionScope
	public User loginBean() {
		return new User();
	}
}

error 메시지 출력을 위한 error.properties 파일 내용 추가

Size.tmpLoginBean.user_id = 사용자 아이디는 5~10글자 사이여야한다.
Pattern.tmpLoginBean.user_id = 사용자 아이디는 영문자 및 숫자로 입력

Size.tmpLoginBean.user_pw = 사용자 비밀번호는 5~10글자 사이여야한다.
Pattern.tmpLoginBean.user_pw = 사용자 비밀번호는 영문자 및 숫자로 입력

- 이전에 작성한 joinBean과 다르게 tmpLoginBean을 사용하는 이유는 에러메시지들이 충돌하는 경우가
생길 수 있기 때문이기도 하고, 회원가입을 처리하는 DAO 메서드의 객체들과 로그인 시 사용하는DAO 메서드에서의 객체의 정보가 겹칠 수 있기 때문에 따로 분리해서 사용한다.


User DTO (로그인 정보 확인)

userLogin 멤버 변수를 boolean 타입으로 선언 후 false로 초기화한다.
이를 통해서 로그인 폼에 진입하는 초기에 로그인이 진행되지 않은 상태가 되어있다.


UserMapper

로그인 시 입력한 정보를 이용해 회원 정보 조회(회원번호, 이름) 

아이디와 비밀번호를 기준으로 DB에 해당 회원 정보가 있는지 확인


UserDao

UserBean을 매개로 회원 정보 조회 메서드 재정

 

tmpLoginBean에 담긴 데이터를 쿼리문에서 사용


UserService 

세션에 저장한 User Bean을 사용하기위해 @Resource(name="loginBean")을 통해 주입받는다.

세션에 저장한 User Bean

만약 Dao에서 쿼리문을 실행한 결과가 존재한다면 반환되는 데이터는 User 객체에 담아준다.
이때, 로그인이 진행된 상태라고 볼 수 있기 때문에 set메서드를 이용해 userLogin은 true로 바꿔준다.

반환되는 데이터가 없는 경우에는 아래의 사진과 같은 텍스트를 추가하기 위해 jsp 페이지와 Controller에 수정이 필요하다

로그인 실패시 화면


login.jsp

로그인 폼 위에 <c:if>태그를 이용해 파라미터명이 fail이며 초기값은 true를 가지도록 설정해주었다.
fail이 true인 경우에만 태그 안의 내용이 페이지에 출력되는 조건을 걸었다고 생각하면 된다.

이를 사용하기 위해 User DTO에서 userLogin 멤버변수를 false로 초기값을 주었는데, 방금 전 Service에서 getLoginUser메서드의 반환되는 데이터가 존재하면 userLogin을 true로 변경해 세션에 저장한다고 했다.

그렇다면 매핑 과정에서 해당 세션의 userLogin의 값을 불러와 로그인 성공과 실패를 정할 수 있다.


UserController

로그인 결과를 지정

@RequestParam으로 login.jsp 페이지에서 fail으로 지정했던 파라미터의 기본 값을 false로 지정한다.
그 후 Model 객체에 저장한다.

이후 로그인 버튼을 클릭하는 경우 user/login_pro 경로로 들어오게 되는데, 이곳에서 유효성 검사에서 오류가 생기면
login 페이지로 돌아가게 설정했다.

ModelAttribute로 로그인 폼에서 데이터를 담은 객체를 지정하여 tmpLoginBean에 저장한 뒤, UserService의 메서드인 getLoginUser를 통해서 회원정보가 존재하는지 여부를 확인한다.
그리고 세션에 저장되어있는 loginBean의 userLogin이 true인지 false인지 나눠 true라면 로그인 후 페이지로 이동하며, 
false인 경우 login_fail 페이지로 이동한다


login_fail

login 페이지로 fail 파라미터의 값을 true로 지정해 이동하게 된다.
fail 파라미터의 값이 true이므로 방금 보았던 로그인 실패 사진과 같이 텍스트가 추가된 모습을 볼 수 있다.

DB에 없는 정보로 로그인 시


login_success

로그인 성공 팝업 창과 함께 main 페이지로 이동한다. - 이 경우 main 페이지의 상단이 변경한다.


topmenu.jsp

<c:choose>태그를 이용해 세션에 저장된 UserBean의 userLogin이 true인 경우와 그렇지 않은 경우로 구분해 화면을 띄운다.

로그인 전 상단 메뉴바 ( 로그인, 회원가입만 뜨는 모습)
로그인 후 상단 메뉴바 ( 정보수정, 로그아웃만 뜨는 모습)


로그아웃

로그인 후 로그아웃을 하는 경우

세션에 저장된 User Bean의 userLogin을 false로 변경해 로그인 상태를 변경한다.

logout.jsp
로그아웃 클릭시


LoginInterceptor

비로그인 상태로 페이지에 접근 시 강제로 로그인 페이지로 이동

package co.ky.sol.interceptor;

public class LoginInterceptor implements HandlerInterceptor {

	@Resource(name = "loginBean")
	private User loginBean;
	
	public LoginInterceptor(User loginBean) {
		this.loginBean = loginBean;
	}
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		//로그인이 되지 않은 경우 return false를 통해 페이지 이동을 막는다.
		if(loginBean.isUserLogin() == false) {
			String str = request.getContextPath();
			response.sendRedirect(str + "/user/not_login");
			return false;
		}
		
		return true;
	}
}

ServletAppContext

비로그인 시 인터셉터에서 Controller 접근 전 처리

LoginInterceptor를 등록하고 "/user/modify", "/board/*" , "/user/delete" 요청에 대해서 preHandle로 처리한다.
excludePathPatterns로 "/board/main" 경로는 제외시킨다.


not_login.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var='root' value='${pageContext.request.contextPath }/'/>
<script>
	alert("로그인 후 이용해 주세요")
	location.href="${root}user/login";

</script>

 

UserController


정보 수정

기본적인 수정 폼은 아래 사진과 같다.
로그인 후 비밀번호를 수정


modify.jsp

<form:form action="${root }user/modify_pro" method="post" modelAttribute="modifyBean">
	<div class="form-group">
		<form:label path="user_name">이름</form:label>
		<form:input path="user_name" class="form-control" readonly="true"/>
	</div>
	<div class="form-group">
		<form:label path="user_id">아이디</form:label>
		<form:input path="user_id" class="form-control" readonly="true"/>
	</div>
	<div class="form-group">
		<form:label path="user_pw">비밀번호</form:label>
		<form:password path="user_pw" class="form-control"/>
		<form:errors path="user_pw" style="color:red"/>
	</div>
	<div class="form-group">
		<form:label path="user_pw2">비밀번호 확인</form:label>
		<form:password path="user_pw2" class="form-control"/>
		<form:errors path="user_pw2" style="color:red"/>
	</div>
	<div class="form-group">
		<div class="text-right">
			<button type="submit" class="btn btn-primary">정보수정</button>
		</div>
	</div>
</form:form>

정보수정 클릭시 modify_pro로 이동하여 추후 작업을 modiify_pro 매핑에서 처리한다.
<form:input>태그는 readonly로 설정해야 파라미터로 주입받을 수 있다.


UserMapper

@Select : 로그인 시 세션에 저장해둔 회원 번호를 이용해 DB에서 해당 데이터를 가져옴
@Update : 수정 폼에서 입력한 데이터를 세션에 저장된 회원 번호를 이용해 DB 업데이트 


UserDAO


UserService

getModify(User modifyBean) : 세션에 저장된 회원 번호를 기준으로 새로운 객체에 데이터 반환 이때 회원번호도 저장

modifyUser(User modifyBean) : 수정 폼에서 입력한 데이터를 저장한 객체에 회원 번호를 세션에 저장된 회원번호 저장


UserValidator

비밀번호가 일치하지 않는 경우를 분류했다.


error.properties

Size.modifyBean.user_pw = 비밀번호는 5자 ~ 10자 사이여야한다.
Pattern.modifyBean.user_pw = 사용자 비밀번호는 영문자 및 숫자로 입력

Size.modifyBean.user_pw2 = 비밀번호는 5자 ~ 10자 사이여야한다.
Pattern.modifyBean.user_pw2 = 사용자 비밀번호는 영문자 및 숫자로 입력

NotEquals.modifyBean.user_pw = 비밀번호가 일치하지 않습니다.
NotEquals.modifyBean.user_pw2 = 비밀번호가 일치하지 않습니다.

에러 메시지 추가


UserController

@ModelAttribute로 수정 폼에서 데이터를 담은 객체를 지정하여 modifyBean에 저장한다.
이후 getModify를 이용해 세션에 저장한다.

modify_pro에서 유효성 검사에서 에러가 발생하지 않으면 modifyUser 메서드를 통해 DB에 정보를 업데이트 한다.
아래 사진처럼 데이터 베이스의 정보가 수정되는 모습을 볼 수 있다.

수정 전 데이터 정보
수정 완료시
수정 후 데이터 정보

Comments