[TIL] #6. 로그인 처리1 - 쿠키, 세션 ①

kiteB·2021년 10월 1일
0

TIL-Spring4

목록 보기
11/17
post-thumbnail

로그인 요구사항

  • 홈 화면 - 로그인 전
    • 회원 가입
    • 로그인
  • 홈 화면 - 로그인 후
    • 본인 이름 (OO님 환영합니다.)
    • 상품 관리
    • 로그아웃
  • 보안 요구사항
    • 로그인 사용자만 상품에 접근하고, 관리할 수 있음
    • 로그인 하지 않은 사용자가 상품 관리에 접근하면 로그인 화면으로 이동
  • 회원 가입, 상품 관리

오늘은 로그인 기능을 구현해보자!


프로젝트 생성

📁 패키지 구조

  • hello.login
    • domain
      • item
      • member
      • login
    • web
      • item
      • member
      • login

파일 구조에서 도메인이 제일 중요하다!

💡 도메인
시스템이 구현해야 하는 핵심 비즈니스 업무 영역 (화면 UI, 기술 인프라 등의 영역 제외)

향후 web을 다른 기술로 바꾸어도 도메인은 그대로 유지할 수 있어야 한다.

이렇게 하려면 web은 domain을 알고 있지만 domain은 web을 모르도록,
즉, web은 domain을 의존, domain은 web을 의존하지 않도록 설계해야 한다.

코드 확인하기

🔗 전체 코드

실행 결과


홈 화면

홈 화면을 개발해보자!

📌 요구사항

  • 홈 화면 - 로그인 전
    • 회원 가입
    • 로그인

코드 확인하기

🔗 전체 코드

실행 결과

홈 화면 요구사항 완료!


회원 가입

이번에는 회원 가입 기능을 구현해보자.

코드 확인하기

🔗 전체 코드

실행 결과

✔ 회원가입 페이지 화면


✔ 회원가입 시 아무런 정보도 입력하지 않았을 때 에러 발생


→ 에러 메시지를 지난 시간에 배운 것을 활용해서 바꿀 수 있다!


✔ 로그인 성공 시

hello.login.web.member.MemberRepository : save: member=Member(id=1, loginId=qwe, name=qwe, password=qwe)

이런 식으로 id, loginId, name, password 정보가 나타난다.


✔ 테스터 추가

ID: test
password: test!

매번 테스트할 때마다 회원가입을 하는 것이 번거로워서 생성하였다.

실행 결과

hello.login.web.member.MemberRepository : save: member=Member(id=1, loginId=test, name=테스터, password=test!)

로그인 기능

이번에는 로그인 기능을 개발해보자!
지금은 로그인 ID, 비밀번호를 입력하는 부분에 집중하자.

코드 확인하기

🔗 전체 코드

LoginService

 public Member login(String loginId, String password) {
    return memberRepository.findByLoginId(loginId)
       .filter(m -> m.getPassword().equals(password))
       .orElse(null);
 }

로그인의 핵심 비즈니스 로직은, 회원을 조회한 뒤 파라미터로 넘어온 password와 비교해서

  • 같으면 회원을 반환
  • 다르면 null을 반환하는 것이다.

LoginController

로그인 컨트롤러는 로그인 서비스를 호출해서

  • 로그인 성공 시 홈 화면 이동
  • 로그인 실패 시
    • bindingResult.reject() 사용해서 글로벌 오류(ObjectError)를 생성
    • 정보를 다시 입력하도록 로그인 폼을 뷰 템플릿으로 사용.

실행 결과

✔ 로그인 성공 시

홈 화면으로 이동


✔ 로그인 실패 시

"아이디 또는 비밀번호가 맞지 않습니다."라는 경고와 함께 로그인 폼 나타남.


✔ 반환 값 확인

  • 로그인 성공 시 → 회원 반환
  • 로그인 실패 시 → null 반환

로그인은 제대로 되지만,
로그인 성공 시 고객의 이름을 보여줘야하는 요구사항을 만족하지 못하고 있다.


로그인 처리하기 - 쿠키 사용

로그인의 상태를 어떻게 유지할 수 있을까?
바로! 쿠키🍪를 사용하면 된다!

쿠키

서버에서 로그인에 성공하면 HTTP 응답에 쿠키를 담아서 브라우저에 전달하면, 브라우저는 앞으로 해당 쿠키를 지속해서 보내준다.

✔ 쿠키 생성

✔ 클라이언트 쿠키 전달 1

✔ 클라이언트 쿠키 전달 2

🍪 쿠키 종류

  • 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지
  • 세션 쿠키: 만료 날짜를 생략하면 브라우저 종료 시까지만 유지

→ 브라우저 종료 시 로그아웃이 되는 것이 우리가 원하는 것이므로, 우리에게 필요한 것은 세션 쿠키이다.


코드 확인하기

쿠키 생성 로직

Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId()));
response.addCookie(idCookie);
  • 로그인에 성공하면 쿠키를 생성하고 HttpServletResponse에 담는다.
  • 쿠키 이름은 memberId이며, 회원의 id를 담아둔다.
  • 웹 브라우저는 종료 전까지 회원의 id를 서버에 계속 보내줄 것이다.

실행 결과

로그인 성공 시 사용자 이름이 출력된다!

🔗 전체 코드


쿠키와 보안 문제

앞에서 쿠키를 사용하여 로그인을 유지할 수 있었는데, 사실 이런 방식에는 심각한 보안 문제가 있다😢

보안 문제

  • 쿠키 값은 임의로 변경할 수 있다.
    • 클라이언트가 쿠키를 강제로 변경하면 다른 사용자가 될 수 있다!
  • 쿠키에 보관된 정보는 훔쳐갈 수 있다.
    • 쿠키에 보관된 정보는 웹 브라우저에도 보관되고, 네트워크 요청마다 계속 클라이언트에서 서버로 전달된다.
    • 그래서 개인정보/신용카드 정보 등이 있다면 쿠키의 정보가 나의 로컬 PC가 털릴 수도 있고, 네트워크 전송 구간에서 털릴 수도 있다.
  • 해커가 쿠키를 한번 훔쳐가면 평생 사용할 수 있다.
    • 해커가 쿠키를 훔쳐가서 그 쿠키로 악의적인 요청을 계속 시도할 수 있다.

대안

  • 쿠키에 중요한 값을 노출하지 않고,
    사용자 별로 예측 불가능한 임의의 토큰(랜덤 값)을 노출하고,
    서버에서 토큰과 사용자 id를 매핑해서 인식한다. 그리고 서버에서 토큰을 관리한다.
  • 토큰은 해커가 임의의 값을 넣어도 찾을 수 없도록 예상 불가능 해야 한다.
  • 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 해당 토큰의 만료시간을 짧게(예: 30분) 유지한다. 또는 해킹이 의심되는 경우 서버에서 해당 토큰을 강제로 제거하면 된다.

다음 시간에 세션을 이용해서 해결할 것이다!

profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글