해당 포스트는 초보 웹 개발자를 위한 스프링 5 프로그래밍 입문 [최범균 저] 책 내용을 참고하였습니다.
로그인 상태를 유지하기 위해서는 HttpSession을 이용하거나 쿠키를 이용하면 된다.
HttpSession을 사용하려면 다음의 두 방법 중 하나를 선택하면 된다.
@PostMapping
public String(loginCommand loginCommand, Errors errors, HttpSession session) {
... // session 사용
}
HttpSession이 생성되어 있으면 기존에 존재하는 걸 사용하고, 아니면 새로 만든다.
@PostMapping
public String(loginCommand loginCommand, Errors errors, HttpServletRequest req) {
HttpSession session = req.getSession();
... // session 사용
}
이 방법을 사용하면 원하는 시점에만 HttpSession을 생성할 수 있다는 장점이 있다.
사용할 때는 setAttribute 메서드를 사용한다.
session.setAttribute("authInfo", authInfo);
로그아웃을 할 때는 HttpSesion을 제거하면 된다.
session.invalidate();
비밀번호를 변경하는 기능은 다음과 같은 순서로 작성한다.
ChangePwdCommand.java - 커맨드 객체
public class ChangePwdCommand {
private String currentPassword;
private String newPassword;
public String getCurrentPassword() {
return currentPassword;
}
public void setCurrentPassword(String currentPassword) {
this.currentPassword = currentPassword;
}
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
}
ChangePwdCommandValidator.java - 커맨드 객체 검증 클래스
public class ChangePwdCommandValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return ChangePwdCommand.class.isAssignableFrom(clazz);
}
@override
public void validate(Object target Error errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "currentPassword", "required");
ValidationUtils.rejectIfEmpty(errors, "newPassword", "required");
}
}
ChangePwdController.java - 비밀번호 변경 요청 처리 컨트롤러
@Controller
@RequestMapping("/edit/changePassword")
public class ChangePwdController {
...
@PostMapping
public String submit(@ModelAttribute("command") ChangePwdCommand pwdCmd, Errors errors, HttpSession session) {
new ChangePwdCommandValidator().validate(pwdComd, errors);
if(errors.hasErrors()) {
return "edit/changePwdForm";
}
AuthInfo authInfo = (AuthInfo) session.getAttribute("authInfo");
...
}
import controller.ChangePwdController;
import spring.ChangePasswordService;
@Configuration
public class ControllerConfig {
@Autoried
private ChangePasswordService changePasswordService;
...
@Bean
public ChangePwdController changePwdCOntroller() {
ChangePwdController controller = new ChangePwdController();
controller.setChangePasswordService(changePasswordService);
return controller;
}
}
로그인하지 않은 상태에서 비밀번호 변경 폼으로 이동했을 때는 어떻게 해야 할까?
이때는 비밀번호 변경 폼 주소를 입력해도 로그인 창으로 넘기는 게 자연스럽다.
if(authInfo == null) {
return "redirect:/login";
}
이러한 세션 점검 코드를 넣어야 할 곳이 많다면? 의도치 않게 중복만 늘어날 것이다.
이때 사용하는 것이 HandlerInterceptor다.
해당 인터페이스를 사용하면 세 시점에 공통 기능을 추가할 수 있다.
우리가 원하는 로그인 여부에 따라 로그인 폼으로 이동하는 로직은 preHandle() 메서드를 사용한다.
HandlerInterceptor 인터페이스의 각 메서드는 아무 기능도 구현하지 않은 디폴트 메서드이므로 필요한 메서드만 재정의하여 사용하면 된다.
public class AuthCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if(session != null) {
Object authInfo = session.getAttribute("authInfo");
if(authInfo != null) {
return true;
}
}
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
}
MvcConfig.java
@Override
public void addInterceptors(InterceptorRegistry registry) { // 인터셉터 설정
registry.addInterceptor(authCheckInterceptor()).addPathPatterns("/edit/**); // 인터셉터를 적용할 경로 패턴 지정
}
다음에 로그인할 때에 이메일을 기억해주는 기능을 추가하고자 한다.
순서는 다음과 같다.
LoginCommand 클래스에 rememberEmail 필드를 작성한다.
public class LoginCommand {
private String email;
private String password;
private boolean rememberEmail;
}
lginForm.jsp - 이메일 기억하기 체크박스 추가
<p>
<!-- label.properties에 rememberEmail=이메일 기억하기 -->
<label><spring:message code="rememberEmail" />:
<form:checkbox path="rememberEmail" />
<label>
</p>
LoginController.java의 form() 메서드 - @CookieValue를 이용해 쿠키를 전달받도록 수정
import javax.servlet.http.Cookie;
import org.springframework.web.bind.annotation.CookieValue;
@GetMapping
// 이름이 REMEMBER인 쿠키를 가져온다
// 쿠키가 없을 수도 있으므로 required는 false로 설정
public String form(LoginCommand loginCommand, @CookieValue(value="REMEMBER", required = false) Cookie rCookie) {
if(rCookie != null) {
loginCommand.setEmail(rCookie.getValue());
loginCommand.setRemeberEmail(true);
}
return "login/loginForm";
}
LoginController.java의 submit() 메서드 - 쿠키 설정
@Controller
@RequestMapping("/login")
public class LoginController {
...
@PostMapping
public String submit(LoginCommand loginCommand, Errors errors, HttpSession session,
HttpServletResponse response) { // 쿠키 생성을 위한 HttpServletResponse 객체
new LoginCommandValidator().validate(LoginCommand, errors);
if(errors.hasErrors()) {
return "login/loginForm";
}
try {
AuthInfo authInfo = authService.authenticate(
loginCommand.getEmail(),
loginCommand.getPassword());
session.setAttribute("authInfo", authInfo);
Cookie rememberCookie = new Cookie("REMEMBER", loginCommand.getEmail());
rememberCookie.setPath("/");
if(loginCommand.isRemeberEmail()) { // 이메일 기억하기 선택했다면
rememberCookie.setMaxAge(60 * 60 * 24 * 30); // 30일 동안 유지되는 쿠키 생성
} else {
rememberCookie.setMaxAge(0); // 바로 삭제되는 쿠키 생성
}
response.addCookie(rememberCookie);
...// 로그인 성공
}
Spring 1
EDITOR: PORO
[스프링1] 15장.간단한 웹 어플리케이션의 구조 (0) | 2022.12.08 |
---|---|
[스프링1] 14장.MVC4 : 날짜 값 변환, @PathVariable, 익셉션 처리 (0) | 2022.12.08 |
[스프링1] 12장. MVC2: 메시지, 커맨드 객체 검증 (0) | 2022.12.01 |
[스프링 1] 11장. MVC1: 요청 매핑, 커맨드 객체, 리다이렉트, 폼 태그, 모델 (0) | 2022.11.24 |
[스프링 1] 10장. 스프링 MVC 프레임워크 동작 방식 (0) | 2022.11.17 |