장성호's
장성호's blog
장성호's
  • 분류 전체보기
    • 알고리즘
      • 백준
      • 이론
    • WEB
      • Spring 인강
      • 네트워크
    • 개인 프로젝트
      • 쇼핑몰 만들기

블로그 메뉴

  • 홈
  • 깃허브
전체 방문자
오늘
어제
반응형
hELLO · Designed By 정상우.
장성호's

장성호's blog

[Spring] 스프링 공부 #29
WEB/Spring 인강

[Spring] 스프링 공부 #29

2022. 4. 17. 02:18
반응형

 

로그인 쿠키 처리

//쿠키에 시간 정보를 주지 않으면 세션 쿠키(브라우저 종료시 모두 종료)
Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId()));
response.addCookie(idCookie);
@GetMapping("/")
public String homeLogin(@CookieValue(name = "memberId", required = false) Long memberId, Model model) {
    if (memberId == null) {
        return "home";
    }

    //로그인
    Member loginMember = memberRepository.findById(memberId);

    if (loginMember == null) {
        return "home";
    }
    model.addAttribute("member", loginMember);
    return "loginHome";
}

 @CookieValue 애노테이션을 사용해서 Cookie에 저장된 값을 조회할 수 있다.

 

@PostMapping("/logout")
public String logout(HttpServletResponse response) {
    expireCookie(response, "memberId");

    return "redirect:/ ";
}

private void expireCookie(HttpServletResponse response, String cookieName) {
    Cookie cookie = new Cookie(cookieName, null);
    cookie.setMaxAge(0);
    response.addCookie(cookie);
}

로그아웃 할 경우, cookie의 시간을 0으로 설정해서 쿠키를 지워준다.

 

하지만, 쿠키 값이 노출된다면

  • 쿠키의 값이 임의로 변경될 문제가 있다.
  • 쿠키에 보관된 정보를 훔쳐갈 수 있는 문제가 있다.
테스터1로 로그인 했을 경우
임의로 memberId를 2로 수정 가능하다.
테스터2로 로그인 된 것처럼 바뀐다.

예상 불가능한 복잡한 세션Id(토큰)을 사용하고, 만료시간을 짧게 설정해서 토큰 정보가 유출되더라도 재사용할 수 없도록 설정한다.

로그인에 세션 적용하기

세션을 생성/관리하는 SessionManager 객체

public class SessionManager {

    public static final String SESSION_COOKIE_NAME = "mySessionId";
    private Map<String, Object> sessionStore = new ConcurrentHashMap<>();

    /**
     * 세선 생성
     */
    public void createSession(Object value, HttpServletResponse response) {

        //세션 id를 생성하고, 값을 세션에 저장
        String sessionId = UUID.randomUUID().toString();
        sessionStore.put(sessionId, value);

        //쿠키 생성
        Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
        response.addCookie(mySessionCookie);
    }

    /**
     * 세션 조회
     */
    public Object getSession(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
        if (sessionCookie == null) {
            return null;
        }
        return sessionStore.get(sessionCookie);
    }

    /**
     * 세션 만료
     */
    public void expire(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
        if (sessionCookie != null) {
            sessionStore.remove(sessionCookie.getValue());
        }
    }

    public Cookie findCookie(HttpServletRequest request, String cookieName) {
        if (request.getCookies() == null) {
            return null;
        }
        return Arrays.stream(request.getCookies())
                .filter(cookie -> cookie.getName().equals(cookieName))
                .findAny()
                .orElse(null);
    }
}

 

세션 매니저를 활용한 로그인 및 로그아웃

@PostMapping("/login")
public String loginV2(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletResponse response) {
    if (bindingResult.hasErrors()) {
        return "login/loginForm";
    }

    Member loginMember = loginService.login(form.getLoginId(), form.getPassword());

    if (loginMember == null) {
        bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
        return "login/loginForm";
    }


    //로그인 성공 처리 TODO

    //세션 매니저를 활용해서 쿠키 처리
    sessionManager.createSession(loginMember, response);

    return "redirect:/";
}

@PostMapping("/logout")
public String logoutV2(HttpServletRequest request) {
    sessionManager.expire(request);
    return "rediredxt:/";
}

 

서블릿에서 제공하는 세션 사용

로그인 및 로그아웃

@PostMapping("/login")
public String loginV3(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request) {
    if (bindingResult.hasErrors()) {
        return "login/loginForm";
    }

    Member loginMember = loginService.login(form.getLoginId(), form.getPassword());

    if (loginMember == null) {
        bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
        return "login/loginForm";
    }


    //로그인 성공 처리 TODO

    //세션이 있을 경우, 기존에 있는 세션 반환
    //없을 경우 신규 세션을 생성
    HttpSession session = request.getSession();
    //세션에 로그인 회원 정보를 보관
    session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);

    return "redirect:/";
}

 @PostMapping("/logout")
public String logoutV3(HttpServletRequest request) {
    //세션이 없을 경우 생성하지 않게 하기 위해서 false
    HttpSession session = request.getSession(false);
    if (session != null) {
        session.invalidate();
    }

    return "redirect:/";
}

 

 

출처

[인프런] 스프링 MVC 2편 - 백엔드 웹 개발 핵심 기술

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

2022.03.31 - [WEB/네트워크] - [네트워크] HTTP 공부 #7  쿠키란?

 

[네트워크] HTTP 공부 #7

HTTP 헤더 HTTP 헤더란? 클라이언트와 서버가 요청 또는 응답으로 부가적인 정보를 전송할 수 있도록 한다. HTTP 전송에 필요한 모든 부가정보를 의미한다. 표현은 요청이나 응답에서 전달할 실제

tjdgh925.tistory.com

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'WEB > Spring 인강' 카테고리의 다른 글

[Spring] 스프링 공부 #31  (0) 2022.04.20
[Spring] 스프링 공부 #30  (0) 2022.04.20
[Spring] 스프링 공부 #28  (0) 2022.04.15
[Spring] 스프링 공부 #27  (0) 2022.04.14
[Spring] 스프링 공부 #26  (0) 2022.04.14
    'WEB/Spring 인강' 카테고리의 다른 글
    • [Spring] 스프링 공부 #31
    • [Spring] 스프링 공부 #30
    • [Spring] 스프링 공부 #28
    • [Spring] 스프링 공부 #27
    장성호's
    장성호's
    장성호's 개발 공부 블로그

    티스토리툴바