스프링 MVC3_ 세션
로그인 성공 후 인증 상태 정보를 세션에 보관할 때 사용할 클래스 생성
package spring;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@AllArgsConstructor
@Getter
@Setter
@ToString
@NoArgsConstructor
public class AuthInfo {
private Long id;
private String email;
private String name;
}
암호 일치여부 확인 및 기본 DTO
package spring;
import java.time.LocalDateTime;
public class Member {
private Long id;
private String email;
private String password;
private String name;
private LocalDateTime registerDateTime;
public Member(String email, String password,
String name, LocalDateTime regDateTime) {
this.email = email;
this.password = password;
this.name = name;
this.registerDateTime = regDateTime;
}
void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public String getName() {
return name;
}
public LocalDateTime getRegisterDateTime() {
return registerDateTime;
}
public void changePassword(String oldPassword, String newPassword) {
if (!password.equals(oldPassword))
throw new WrongIdPasswordException();
this.password = newPassword;
}
public boolean mathPassword(String password) {
return this.password.equals(password);
}
}
DAO
package spring;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
public class MemberDao {
private JdbcTemplate jdbcTemplate;
public MemberDao(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public Member selectByEmail(String email) {
List<Member> results = jdbcTemplate.query(
"select * from MEMBER where EMAIL = ?",
new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member member = new Member(
rs.getString("EMAIL"),
rs.getString("PASSWORD"),
rs.getString("NAME"),
rs.getTimestamp("REGDATE").toLocalDateTime());
member.setId(rs.getLong("ID"));
return member;
}
}, email);
return results.isEmpty() ? null : results.get(0);
}
}
이메일 비밀번호 일치 확인 후 객체를 생성하는 서비스 클래스 생성
package spring;
public class AuthService {
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public AuthInfo authenticate(String email, String password) {
Member member = memberDao.selectByEmail(email);
if(member == null) {
throw new WrongIdPasswordException();
}
if(!member.mathPassword(password)) {
throw new WrongIdPasswordException();
}
return new AuthInfo(member.getId(),
member.getEmail(),
member.getName());
}
}
에러처리
package spring;
public class WrongIdPasswordException extends RuntimeException {
}
폼에 입력한 값을 전달받기 위한 Login커맨드 클래스 생성
package controller;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class LoginCommand {
private String email;
private String password;
private boolean rememberEmail;
public boolean isRememberEmail() {
return rememberEmail;
}
public void setRememberEmail(boolean rememberEmail) {
this.rememberEmail = rememberEmail;
}
}
입력값이 올바른지 확인하기 위한 Validator 클래스 생성
package controller;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
public class LoginCommandValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return LoginCommand.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "required");
ValidationUtils.rejectIfEmpty(errors, "password", "required");
}
}
로그인 요청 처리 controller 클래스 생성 ( 세션정보 저장 )
package controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
import spring.AuthInfo;
import spring.AuthService;
import spring.WrongIdPasswordException;
@Controller
@RequestMapping("/login")
@Slf4j
public class LoginController {
private AuthService authService;
public void setAuthService(AuthService authService) {
this.authService = authService;
}
@GetMapping
public String form(LoginCommand loginCommand) {
return "login/loginForm";
}
@PostMapping
public String submit(LoginCommand loginCommand, Errors errors, HttpSession session) {
new LoginCommandValidator().validate(loginCommand, errors);
if(errors.hasErrors()) {
return "login/loginForm";
}
try {
AuthInfo authInfo = authService.authenticate(loginCommand.getEmail(),
loginCommand.getPassword());
// 로그인 session 테스트
session.setAttribute("authInfo", authInfo);
session.setAttribute("test", authInfo);
AuthInfo authInfo1 = (AuthInfo) session.getAttribute("authInfo");
log.info("-----login------->" + authInfo1);
return "login/loginSuccess";
} catch (WrongIdPasswordException e) {
errors.reject("idPasswordNotMatching");
return "login/loginForm";
}
}
}
로그아웃 controller
package controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
import spring.AuthInfo;
@Controller
@Slf4j
public class LogoutController {
@RequestMapping("/logout")
public String logout(HttpSession session) {
// 로그아웃 session 테스트
AuthInfo authInfo = (AuthInfo) session.getAttribute("authInfo");
log.info("------logout------>" + authInfo);
session.invalidate();
return "redirect:/main";
}
}
컨트롤러, 서비스 스프링 빈 등록
package config;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import controller.LogoutController;
import spring.AuthService;
import spring.MemberDao;
@Configuration
@EnableTransactionManagement
public class MemberConfig {
@Bean(destroyMethod = "close")
public DataSource dataSource() {
DataSource ds = new DataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
ds.setUsername("spring5");
ds.setPassword("spring5");
ds.setInitialSize(2);
ds.setMaxActive(10);
ds.setTestWhileIdle(true);
ds.setMinEvictableIdleTimeMillis(60000 * 3);
ds.setTimeBetweenEvictionRunsMillis(10 * 1000);
return ds;
}
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager tm = new DataSourceTransactionManager();
tm.setDataSource(dataSource());
return tm;
}
@Bean
public MemberDao memberDao() {
return new MemberDao(dataSource());
}
@Bean
public AuthService authService() {
AuthService authService = new AuthService();
authService.setMemberDao(memberDao());
return authService;
}
@Bean
public LogoutController logoutController() {
return new LogoutController();
}
}
package config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import controller.LoginController;
import spring.AuthService;
@Configuration
public class ControllerConfig {
@Autowired
private AuthService authService;
@Bean
public LoginController loginController() {
LoginController controller = new LoginController();
controller.setAuthService(authService);
return controller;
}
}
package config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/view/", ".jsp");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/main").setViewName("main");
}
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource ms =
new ResourceBundleMessageSource();
ms.setBasenames("message.label");
ms.setDefaultEncoding("UTF-8");
return ms;
}
}
스프링 메세지
member.register=회원가입
term=약관
term.agree=약관동의
next.btn=다음단계
member.info=회원정보
email=이메일
name=이름
password=비밀번호
password.confirm=비밀번호 확인
register.btn=가입 완료
register.done=<strong>{0}님 ({1})</strong>, 회원 가입을 완료했습니다.
go.main=메인으로 이동
required=필수항목입니다.
bad.email=이메일이 올바르지 않습니다.
duplicate.email=중복된 이메일입니다.
nomatch.confirmPassword=비밀번호와 확인이 일치하지 않습니다.
login.title = 로그인
login.btn = 로그인하기
idPasswordNotMatching=아이디와 비밀번호가 일치하지 않습니다.
login.done=로그인에 성공했습니다.
main.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>메인</title>
</head>
<body>
<c:if test="${empty authInfo }">
<p>환영합니다.</p>
<p><a href="<c:url value="/register/step1" />">[회원 가입하기]</a>
<a href="<c:url value="/login"/>">[로그인]</a>
</p>
</c:if>
<c:if test="${! empty authInfo }">
<p>${authInfo.name}님, 환영합니다.</p>
<p><a href="<c:url value="/edit/changePassword" />">[비밀번호 변경]</a>
<a href="<c:url value="/logout"/>">[로그아웃]</a>
</p>
</c:if>
</body>
</html>
loginForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><spring:message code="login.title" /></title>
</head>
<body>
<form:form modelAttribute="loginCommand">
<form:errors />
<p>
<label><spring:message code="email" />:<br>
<form:input path="email" />
<form:errors path="email" />
</label>
</p>
<p>
<label>
<spring:message code="password" />:<br>
<form:password path="password" />
<form:errors path="password" />
</label>
</p>
<input type="submit" value="<spring:message code="login.btn" />">
</form:form>
</body>
</html>
loginSuccess.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><spring:message code="login.title" /></title>
</head>
<body>
<p>
<spring:message code="login.done" />
</p>
<p>
<a href="<c:url value='/main'/>">
[<spring:message code="go.main" />]
</a>
</p>
</body>
</html>