JAVA Spring #6

keymu·2024년 11월 14일
0

동일한 user의 computer라 하더라도 session, cookie는 브라우저가 다르면 다르게 관리한다. cookie, session은 브라우저가 관리한다.

  • Server: Cookie 생성 -> Response에 담아 보냄
  • Browser: Cookie 저장
  • Browser: 다음 요청 보낼 때 Cookie 담아보냄
  • Server: 내가 보냈던 거란 걸 알고 클라이언트 상세 정보를 저장(name value 쌍)

네트워크 연결성

  • connection도 system 자원이므로, 웹은 request, response가 완료되면 접속이 끊어짐 (= 통신의 연속성이 없음)
  • 쿠키의 등장

Spring 환경에서 Cookie 다루는 법
1. Severlet의 HttpServletResponse 객체 사용
2. CookieValue("key") 사용

package com.lec.spring.controller5;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Controller
@RequestMapping("/cookie")
public class CookieController {

    // 클라이언트로부터 온 request 안의 cookie 정보들 조회
    @RequestMapping("/list")
    public void list(HttpServletRequest request, Model model){
        // 클라이언트 안의 쿠키 정보는 request 시에 서버로 전달된다.
        // request.getCookies() 로 쿠키 받아올수 있다.
        Cookie[] cookies = request.getCookies();

        StringBuffer buff = new StringBuffer();

        if(cookies != null){  // 쿠키가 하나도 없다면 null 을 리턴한다
            for (int i = 0; i < cookies.length; i++) {
                // Cookie 는 name-value 쌍으로 이루어진 데이터 (name, value 는 모두 String)
                String name = cookies[i].getName();
                String value = cookies[i].getValue();
                buff.append((i + 1) + "] " + name + " : " + value + "<br>");
            }

        } else {
            buff.append("쿠키가 없습니다<br>");
        }

        model.addAttribute("result", buff.toString());

    }

    // 쿠키 생성 절차
    //1. 쿠키(Cookie) 클래스로 생성
    //2. 쿠키속성 설정(setter)
    //3. 쿠키의 전송 (response 객체에 탑재:addCookie())
    @RequestMapping("/create")
    public String create(HttpServletResponse response) throws IOException {
        String cookieName1 = "num1";
        String cookieValue1 = "" + (int)(Math.random() * 10);
        Cookie cookie1 = new Cookie(cookieName1, cookieValue1);  // name-value 쌍으로 Cookie 생성
        cookie1.setMaxAge(30); // 쿠키 파기(expiry) 시간 설정 (생성 시점으로부터 30 초 후)
        response.addCookie(cookie1);  // response 에 Cookie 추가

        // 쿠키는 얼마든지 생성 가능
        String cookieName2 = "datetime";
        String cookieValue2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss"));

        Cookie cookie2 = new Cookie(cookieName2, cookieValue2);
        cookie2.setMaxAge(45);
        response.addCookie(cookie2);

        // response.sendRedirect("/cookie/list");
        return "redirect:/cookie/list";
    }

    @RequestMapping("/delete")
    public String delete(HttpServletResponse response){
        String cookieName = "num1";  // 삭제할 cookie 의 name
        Cookie cookie = new Cookie(cookieName, "");
        cookie.setMaxAge(0);   // response 되자마자 해당 name 의 cookie 는 삭제됨.
        response.addCookie(cookie);

        return "redirect:/cookie/list";
    }

    @RequestMapping("/num1")
    @ResponseBody
    public String num1(@CookieValue(value = "num1", required = false) Cookie cookie){

        if(cookie != null){
            return cookie.getName() + " : " + cookie.getValue();
        }

        return "num1 쿠키 없어요";
    }

    //------------------------------------------------------------------------
    public static final String ADMIN_ID = "admin";
    public static final String ADMIN_PW = "1234";

    @GetMapping("/login")
    public void login(@CookieValue(name="username", required = false) String username, Model model){
        model.addAttribute("username", username);
    }

    @PostMapping("/login")
    public String loginOk(String username, String password, HttpServletResponse response, Model model){
        // username /password 일치하면 인증성공 -> 쿠키 발급
        if(ADMIN_ID.equalsIgnoreCase(username) && ADMIN_PW.equals(password)){
            Cookie cookie = new Cookie("username", username);
            cookie.setMaxAge(30);
            response.addCookie(cookie);

            model.addAttribute("result", true);
        } else {
            Cookie cookie = new Cookie("username", username);
            cookie.setMaxAge(0);   // 기존에 혹시 있었을 쿠키도 삭제한다.
            response.addCookie(cookie);
        }

        return "cookie/loginOk";
    }

    @PostMapping("/logout")
    public String logout(HttpServletResponse response){
        Cookie cookie = new Cookie("username", "");
        cookie.setMaxAge(0);   // 기존에 혹시 있었을 쿠키도 삭제한다.
        response.addCookie(cookie);

        return "cookie/logout";
    }


}

Session

  • Client의 상태를 기억하는 웹 기술
  • Client: Request
  • Server: new Client의 상세정보 저장 위한 (name-value쌍) 테이블 형성 / 오로지 이 Client만을 위한(고유한 Id가 있는) table = session => Cookie에 비해 보안성이 높고 제한이 크게 없음
  • Session Reponse값에 쿠기 Session id 끼워서 보냄
  • 클라이언트가 이 쿠키를 보게 됨
  • Client: 다시 request 보낼 때 cookie의 Session id를 넣어 보냄 (Session id에는 무엇이든 들어갈 수 있음)

Spring이 session을 다루는 법
1. HttpSession object 사용
2. @SessionAttribute 사용
3. Model에 저장 시, session, request에 저장 (RedirectAttribute도 내부적으로 session 사용)

package com.lec.spring.controller5;

import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Enumeration;

@Controller
@RequestMapping("/session")
public class SessionController {

    // HttpSession 객체
    //  현재 request 한 client 에 대한 Session 정보
    //  session 은 attribute(name-value쌍) 들이 담겨 있다
    //   name: String 타입,  value: Object 타입
    @RequestMapping("/list")
    public void list(HttpSession session, Model model){
        Enumeration<String> enumeration = session.getAttributeNames();

        StringBuffer buff = new StringBuffer();

        int i = 0;
        while(enumeration.hasMoreElements()){
            String sessionName = enumeration.nextElement();
            // session.getAttribute('name')  <-- 특정 세션 attr value 추출. 리턴타입 Object. 해당 name 이 없으면 null 리턴
            String sessionValue = session.getAttribute(sessionName).toString();

            buff.append((i + 1) + "] " + sessionName + " : " + sessionValue + "<br>");
            i++;
        }
        if(i == 0){
            buff.append("세션 안에 attribute 가 없습니다<br>");
        }

        model.addAttribute("result", buff.toString());
    }

    @RequestMapping("/create")
    public String create(HttpSession session){
        String sessionName, sessionValue;

        sessionName = "num1";
        sessionValue = "" + (int)(Math.random() * 100);

        // 세션 attr : name-value 생성
        // setAttribute(String name, Object value) 두번째 매개변수는 Object 타입이다
        session.setAttribute(sessionName, sessionValue);

        sessionName = "datetime";
        sessionValue = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
        session.setAttribute(sessionName, sessionValue);

        return "redirect:/session/list";
    }

    @RequestMapping("/delete")
    public String delete(HttpSession session){
        // removeAttribute(name) 세션 attribute 삭제
        session.removeAttribute("num1");
        return "redirect:/session/list";
    }

    //-------------------------------------------------
    public static final String ADMIN_ID = "admin";
    public static final String ADMIN_PW = "1234";

    @GetMapping("/login")
    public void login(HttpSession session, Model model){
        // 현재 로그인 상태인지, 즉 로그인 세션 (name이 'username'인 세션값)이 있는지 확인
        if(session.getAttribute("username") != null){
            model.addAttribute("username", session.getAttribute("username"));
        }
    }

    @PostMapping("/login")
    public String loginOk(String username, String password, HttpSession session
            , Model model){

        // 세션 name-value 지정
        String sessionName = "username";
        String sessionValue = username;

        // 제출된 id /pw 값이 일치하면 로그인 성공 + 세션 attr 생성
        if(ADMIN_ID.equalsIgnoreCase(username) && ADMIN_PW.equals(password)){
            session.setAttribute(sessionName, sessionValue);
            model.addAttribute("result", true);
        }else{
            session.removeAttribute(sessionName);
        }

        return "session/loginOk";
    }

    @PostMapping("/logout")
    public String logout(HttpSession session){

        String sessionName = "username";

        // 세션 삭제
        session.removeAttribute(sessionName);

        return "session/logout";
    }

}
profile
Junior Backend Developer

0개의 댓글