[boostcourse] 5.5. Spring MVC에서의 Session 사용하기 - BE

세션 관련 애노테이션

@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();
    }
}

 

Session MVC에서의 Session  실습하기

요구사항

- 관리자는 /loginform에서 암호를 입력해 로그인을 함

- 관리자가 암호를 맞게 입력할 경우, 세션에 로그인 정보가 저장됨

- 세션에 로그인 정보가 있을 경우, 방명록에는 "삭제" 링크가 보여짐

- 삭제 링크를 누르면 삭제됨. 삭제 작업에서도 로그인 정보가 있는지 검사해야 함

 

세션을 사용하여 로그인하기

# GuestbookAdminController.java

package com.example.guestbook.controller;

import jakarta.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.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 httpSession,
                        RedirectAttributes redirectAttributes) {

        if("1234".equals(passwd)) {
            System.out.println("same password");
            httpSession.setAttribute("isAdmin", "true");
        }
        else {
            redirectAttributes.addFlashAttribute("errorMessage", "암호가 틀렸습니다.");
            return "redirect:/loginform";
        }
        return "redirect:list";
    }
}

 

# loginform.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>loginform</title>
</head>
<body>
    <h1>관리자 로그인</h1>
    <br><br>
    ${errorMessage}<br>

    <form method="post" action="login">
        암호: <input type="password" name="passwd"><br>
        <input type="submit">
    </form>
</body>
</html>

 

방명록 삭제하기

암호가 틀렸을 경우, /loginform으로 리다이렉트

etc-image-0

암호가 맞다면, /list로 리다이렉트

etc-image-1

 

삭제 클릭하면 해당 방명록 삭제

# list.jsp

<%--
  Created by IntelliJ IDEA.
  User: jeonsoyeong
  Date: 2023/06/27
  Time: 6:47 PM
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>방명록 목록</title>
</head>
<body>
    <h1>방명록</h1>
    <br> 방명록 전체 수 : ${count }, 방문한 수 : ${cookieCount }
    <br>
    <br>

    <c:forEach items="${list}" var="guestbook">
        ${guestbook.id} ${status.index}<br>
        ${guestbook.name} ${status.index}<br>
        ${guestbook.content} ${status.index}<br>
        ${guestbook.regdate} ${status.index}<br>
        <c:if test="${sessionScope.isAdmin == 'true'}"><a href="delete?id=${guestbook.id}">삭제</a><br><br></c:if>
    </c:forEach>
    <br>

    <c:forEach items="${pageStartList}" var="pageIndex" varStatus="status">
        <a href="list?start=${pageIndex}">${status.index +1 }</a>&nbsp; &nbsp;
    </c:forEach>

    <br>
    <br>
    <form method="post" action="write">
        name : <input type="text" name="name"><br>
        <textarea name="content" cols="60" rows="6"></textarea>
        <br> <input type="submit" value="등록">
    </form>
</body>
</html>

 

# GuestbookController.java

더보기

23.07.11

- 세션의 isAdmin : true 값 존재 여부 확인해서 삭제하기

- 오류 발생

list.jsp에서 sessionScore.isAdmin == 'true' 는 잘 인식하는데

컨트롤러 메소드에서 @SessionAttribute("isAdmin") String isAdmin 이렇게 읽어온 isAdmin 값은 못 가져온다 ㅠ

그래서 삭제 아직 미구현 상태..

너무 졸리니까 내일 봐야게따 ㅠ

 

23.07.16

알고보니 GuestbookController에서 equals()로 비밀번호 일치 여부 검사하는데 !을 안붙여줘서 삭제가 안됐었다 ㅋㅋ

맑은 정신으로 코드 찬찬히 읽어보니 바로 보이죠;;;

    @GetMapping(path="/delete")
    public String delete(@RequestParam(name = "id", required = true) Long id,
                         @SessionAttribute("isAdmin") String isAdmin,
                         HttpServletRequest request,
                         RedirectAttributes redirectAttributes) {
        if(isAdmin == null || !"true".equals(isAdmin)) {
            redirectAttributes.addFlashAttribute("errorMessage", "로그인을 하지 않았습니다.");
            return "redirect:loginform";
        }

        String clientIp = request.getRemoteAddr();
        guestbookService.deleteGuestbook(id, clientIp);
        return "redirect:list";
    }

etc-image-2

1. /loginform으로 요청. 비밀번호 입력하기

2. 비밀번호를 입력받아 /login으로 요청해서 로그인하기. httpSession에 ("isAdmin", "true) 값 설정해주기

3. 로그인 성공 시 /list로 리다이렉트하기

4. /delete로 삭제 요청을 한다면, @SessionAttribute("isAdmin")을 통해 로그인 여부 검증한 후 삭제하기

5. 삭제 성공 시 /list로 리다리엑트하기

etc-image-3
id 7인 레코드 잘 삭제되었음

로그아웃하기

# GuestbookAdminController.java

    @GetMapping(path="/logout")
    public String logout(HttpSession session) {
        session.removeAttribute("isAdmin");
        return "redirect:/list";
    }