Spring MVC에서 Session 사용하기 - accidentlywoo/legacyVue GitHub Wiki

Spring MVC에서 Session 사용하기

  • 들어가기 전에 이번 시간엔 Spring MVC에서 제공하는 세션 관련 애노테이션에 대해 알아보고, 해당 애노테이션을 사용해 보도록 하겠습니다.

학습 목표

  1. Spring MVC에서 제공하는 세션 관련 애노테이션에 대해 이해한다.
  2. Spring MVC를 이용한 웹 어플리케이션에 세션 관련 애노테이션을 적용할 수 있다.

핵심 개념

  • @SessionAttributes
  • @ModelAttribute
  • @SessionAttribute
  • SessionStatus

학습하기

@SessionAttributes & @ModelAttribute

@SessionAttributes 파라미터로 지정된 이름과 같은 이름이 @ModelAttribute에 지정되어 있을 경우 메소드가 반환되는 값은 세션에 저장됩니다. 아래의 예제는 세션에 값을 초기화하는 목적으로 사용되었습니다. @SessionAttributes("user") public class LoginController { @ModelAttribute("user") public User setUpUserForm() { return new User(); } }

@SessionAttributes의 파라미터와 같은 이름이 @ModelAttribute에 있을 경우 세션에 있는 객체를 가져온 후, 클라이언트로 전송받은 값을 설정합니다. @Controller @SessionAttributes("user") public class LoginController { ...... @PostMapping("/dologin") public String doLogin(@ModelAttribute("user") User user, Model model) { ...... } }

@SessionAttribute 메소드에 @SessionAttribute가 있을 경우 파라미터로 지정된 이름으로 등록된 세션 정보를 읽어와서 변수에 할당합니다. @GetMapping("/info") public String userInfo(@SessionAttribute("user") User user) { //... //... return "user"; }

*** SessionStatus *** SessionStatus는 컨트롤러 메소드의 파라미터로 사용할 수 있는 스프링 내장 타입입니다. 이 오브젝트를 이용하면 현재 컨트롤러의 @SessionAttributes에 의해 저장된 오브젝트를 제거할 수 있습니다. `@Controller @SessionAttributes("user") public class UserController { ...... @RequestMapping(value = "/user/add", method = RequestMethod.POST) public String submit(@ModelAttribute("user") User user, SessionStatus sessionStatus) { ...... sessionStatus.setComplete(); ......

} }`

*** Spring MVC - form tag 라이브러리 *** modelAttribute속성으로 지정된 이름의 객체를 세션에서 읽어와서 form태그로 설정된 태그에 값을 설정합니다. <form:form action="login" method="post" modelAttribute="user"> Email : <form:input path="email" /><br> Password : <form:password path="password" /><br> <button type="submit">Login</button> </form:form>

실습코드

  • 관리자는 /loginform에서 암호를 입력해 로그인을 한다.
  • 관리자가 암호를 맞게 입력할 경우 세션에 로그인 정보가 저장된다.
  • 세션에 로그인 정보가 있을 경우 방명록에는 "삭제"링크가 보여진다.
  • 삭제 링크를 누르면 삭제가 된다. 삭제 작업에서도 로그인 정보가 있는지를 검사해야 한다.

GuestbookAdminController.java ` package kr.or.connect.guestbook.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.support.SessionStatus; import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller public class GuestbookAdminController {

   @GetMapping(path="/loginform")
	public String loginform() {
		return "loginform";
	}
	
    @PostMapping(path="/login")
	public String login(@RequestParam(name="passwd", required=true) String passwd, 
			HttpSession session,
			RedirectAttributes redirectAttr) {
		
		if("1234".equals(passwd)) {
			session.setAttribute("isAdmin", "true");
		}else {
			redirectAttr.addFlashAttribute("errorMessage","암호가 틀렸습니다.");
			return "redirect:/loginform";
		}
		return "redirect:/list";
	}
	
   @GetMapping(path="/logout")
	public String login(HttpSession session) {
		session.removeAttribute("isAdmin");
		return "redirect:/list";
	}

}`

loginform.jsp `<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<title>loginform</title>

관리자 로그인



${errorMessage}
암호 :
` 기존 코드에서 /delete 삭제 부분을 추가합니다. 세션에 isAdmin 이름의 값이 있을 경우에만 삭제 처리를 하도록 합니다.

GuestbookController.java `package kr.or.connect.guestbook.controller;

import java.util.ArrayList; import java.util.List;

import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttribute; import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import kr.or.connect.guestbook.dto.Guestbook; import kr.or.connect.guestbook.service.GuestbookService;

@Controller public class GuestbookController { @Autowired GuestbookService guestbookService;

@GetMapping(path="/list")
public String list(@RequestParam(name="start", required=false, defaultValue="0") int start,
				   ModelMap model, @CookieValue(value="count", defaultValue="1", required=true) String value,
				   HttpServletResponse response) {
	
	try {
		int i = Integer.parseInt(value);
		value = Integer.toString(++i);
	}catch(Exception ex){
		value = "1";
	}
	
	Cookie cookie = new Cookie("count", value);
	cookie.setMaxAge(60 * 60 * 24 * 365); // 1년 동안 유지.
	cookie.setPath("/"); // / 경로 이하에 모두 쿠키 적용. 
	response.addCookie(cookie);
	
	List<Guestbook> list = guestbookService.getGuestbooks(start);
	
	int count = guestbookService.getCount();
	int pageCount = count / GuestbookService.LIMIT;
	if(count % GuestbookService.LIMIT > 0)
		pageCount++;
	
	List<Integer> pageStartList = new ArrayList<>();
	for(int i = 0; i < pageCount; i++) {
		pageStartList.add(i * GuestbookService.LIMIT);
	}
	
	model.addAttribute("list", list);
	model.addAttribute("count", count);
	model.addAttribute("pageStartList", pageStartList);
	model.addAttribute("cookieCount", value);
	
	return "list";
}

@PostMapping(path="/write")
public String write(@ModelAttribute Guestbook guestbook,
					HttpServletRequest request) {
	String clientIp = request.getRemoteAddr();
	System.out.println("clientIp : " + clientIp);
	guestbookService.addGuestbook(guestbook, clientIp);
	return "redirect:list";
}


@GetMapping(path="/delete")
public String delete(@RequestParam(name="id", required=true) Long id, 
		             @SessionAttribute("isAdmin") String isAdmin,
		             HttpServletRequest request,
		             RedirectAttributes redirectAttr) {
	if(isAdmin == null || !"true".equals(isAdmin)) { // 세션값이 true가 아닐 경우
		redirectAttr.addFlashAttribute("errorMessage", "로그인을 하지 않았습니다.");
		return "redirect:loginform";
	}
	String clientIp = request.getRemoteAddr();
	guestbookService.deleteGuestbook(id, clientIp);
	return "redirect:list";		
}

}`

기존 list.jsp에서 isAdmin세션값이 있을 경우 삭제 링크를 걸업줍니다. `<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<title>방명록 목록</title>

방명록


방명록 전체 수 : ${count }, 방문한 수 : ${cookieCount }

<c:forEach items="${list}" var="guestbook">

${guestbook.id }
${guestbook.name }
${guestbook.content }
${guestbook.regdate }
<c:if test="${sessionScope.isAdmin == 'true'}">삭제

</c:if> </c:forEach>

<c:forEach items="${pageStartList}" var="pageIndex" varStatus="status"> ${status.index +1 }    </c:forEach>



name :
<textarea name="content" cols="60" rows="6"></textarea>
`

생각해보기

  1. Spring에서는 인증 등을 처리하기 위해 Spring Security라는 모듈을 제공합니다. 우리 수업에서는 Spring Security를 다루지 않고 있는데요. Spring을 이용한 상용 웹 어플리케이션에서는 굉장히 많이 사용되고 있습니다. 모든 과정을 학습한 이후에 Spring Security를 별도로 학습해서 인증처리 구현을 한번 해보세요.
⚠️ **GitHub.com Fallback** ⚠️