12. 로그인 기능 구현
이제는 실제 사용자의 정보를 이용해 로그인 기능을 구현해 보자.
우리가 해야하는 일은 DB에 저장된 정보와 로그인을 위해 입력한 정보를 비교하기 위한 Service 클래스를 생성하고, Controller와 DAO 사이에서 둘을 적절하게 연결시켜 주는 것이다.
확인을 편하게 하기 위해 기본적으로 들어가 있는 더미 데이터도 저장해 주자.
로그인 기능 구현
DAO 수정
이제, 우리는 입력된 아이디와 비밀번호를 사용해 유저 정보를 조회해야 한다.
조금 더 추상화 해, 파라미터들을 전달해 주면 해당 파라미터들을 사용해 데이터를 조회하는 기능을 DAO에 추가해 주자.
가장 먼저, 인터페이스에 메서드를 하나 추가해 준다.
<R> R getObjectByParameters(String sql,
Function<ResultSet, R> mapper,
String... params) throws SQLException;
params로 전달된 값들을 차례대로 sql에 매핑한 후 데이터를 조회해 R 타입 객체를 반환하는 메서드이다.
다음으로, DaoContext에 해당 메서드를 구현하자.
@Override
public <R> R getObjectByParameters(String sql,
Function<ResultSet, R> mapper,
String... params) throws SQLException {
R returnObject = null;
try (Connection conn = getConnect()) {
PreparedStatement ps = conn.prepareStatement(sql);
for(int i = 0; i<params.length; i++)
ps.setString(i+1, params[i]);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
returnObject = mapper.apply(rs);
}else{
throw new NoDataFoundedException();
}
}
return returnObject;
}
params로 전달된 파라미터들을 sql에 바인딩하고, 객체를 생성하는 코드이다.
마지막으로 UserDAO에서 해당 메서드를 사용해 유저 정보를 가져오자.
public User findUserByIdAndPW(String id, String pw)
throws SQLException {
String sql =
"select * from users where id = ? and password = ?";
User user = daoContext.getObjectByParameters
(sql, userMapper, id, pw);
return user;
}
Service 수정
UserService 에서는 로그인 세션의 값을 받아오는 메서드를 생성해 주었다.
일단 임시로 유저의 idx 값을 로그인 세션 값으로 반환하였다.
public String getLoginSession(String id, String pw)
throws SQLException {
User user = userDAO.findUserByIdAndPW(id, pw);
return Integer.toString(user.getIdx());
}
Controller 수정
이제 로그인이 성공했을 때는 제대로 된 세션 값을 전달해 주고, 그렇지 않을 때는 실패 페이지로 이동하자.
UserController
@PostMapping("/login")
public String login(HttpSession session, ServletRequest request) {
System.out.println("success login");
String id = request.getParameter("id");
String pw = request.getParameter("password");
try {
String loginSession = userService.getLoginSession(id, pw);
session.setAttribute("userIdx", loginSession);
session.setMaxInactiveInterval(30 * 60);
return viewPath + "successLogin";
} catch (SQLException e) {
return viewPath + "failedLogin";
}
}
failedLogin.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<body>
<div class="container">
로그인 실패!
</div>
</body>
</html>
더미 데이터 삽입
어플리케이션을 생성하는 즉시 더미 데이터를 삽입해 주어 테스트를 편리하게 만들어 주기 위해 data.sql 파일을 resource 폴더 아래에 생성해 준다.
insert into users(id, password) values ('TempUser', 'TempPassword');
동작 확인
더미데이터 삽입 확인
서버를 실행시키자 마자 db에서 값을 확인하면 다음과 같은 더미 데이터가 확인된다.
로그인 기능 확인
잘못된 아이디, 또는 비밀번호를 입력하면
로그인에 실패하고
제대로 된 값을 입력하면
로그인이 성공하여
세션이 유지된다.
로그아웃 기능
로그아웃 기능은 간단하다.
기존의 세션을 유요하지 않도록 만들어 주면 된다.
이제 이미 로그인이 되어 있는 경우에는 로그아웃 버튼을 추가하여 로그아웃을 할 수 있도록 하자.
<!--login.jsp-->
<!-- ... -->
<p>이미 로그인이 되어있습니다.</p>
<a href="http://localhost:8080/user/logout">로그아웃</a>
<!-- ... -->
그리고 컨트롤러에도 필요 메서드를 생성한다.
@GetMapping("/logout")
public String logout(HttpSession session){
session.invalidate();
return viewPath + "login";
}
로그인이 성공하면 다음과 같이 표시가 되고
다시 로그인을 시도하면 다음의 창이 보여진다.
로그아웃을 누르면 다시 로그인을 할 수 있도록 세션이 만료된다.