Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

권지후 5주차 과제 제출 #2

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions jihoo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# 사용자 관점에서의 로그인 과정 흐름

### 로그인 과정
- 사용자가 로그인 화면을 통해 ID와 비밀번호 필드 입력 후 로그인 버튼을 누르면 입력된 정보가 서버로 전송된다.
- (클라이언트에서 로그인 요청(POST /api/members/login)을 보내며, `memberService.login` 메소드에 사용자 ID와 비밀번호가 담긴 loginReqDto을 전달한다. `memberRepository.findByLoginId()`를 사용해 사용자가 존재하는지 확인하고 없으면 `IllegalArgumentException` 발생, `validationPassword()` 메소드에서 `encoder.matches()`를 사용하여 비밀번호 검증 후 일치하지 않으면 `IllegalStateException` 발생)

### 로그인 성공 시
- 전달받은 ID와 비밀번호가 DB에 저장된 정보와 비교해 인증 성공 시 로그인이 성공되어 메인 홈(로그인 성공 응답 HTTP)으로 리다이렉션 된다.
- (이때 서버는 인증된 사용자에 대해 세션을 생성하고, `SecurityContext`를 세션에 저장하여 인증 상태를 관리. 클라이언트는 이후 요청에서 쿠키로 저장된 세션 ID를 이용해 인증 상태를 유지하며, 서버는 이를 통해 사용자를 식별할 수 있게 된다.)

### 로그인 실패 시
- 서버에서 전달받은 ID 또는 비밀번호가 일치하지 않을 시 `ID 또는 비밀번호가 잘못되었습니다`라는 오류 메세지로 로그인 실패를 반환받고, 사용자는 동일한 로그인 화면에서 로그인을 다시 시도할 수 있다.

### 사용자 관점에서의 로그인 성공 및 로그인 유지 경험
- 로그인을 성공한다면 사용자는 웹페이지 내에서 자신의 권한 내 허용된 페이지에 대한 여러 요청을 보낼 때 자신의 계정이 유지되고, 브라우저를 닫았다가 열어도 로그인 상태가 일정 기간 동안 유지된다.
- (이때 서버는 `SecurityConfig`에서의 보안 설정을 통해서 사용자가 요청한 리소스에 대한 인증과 권한을 확인한 후 허용된 페이지에만 접근할 수 있도록 한다.`SecurityConfig`에서 세션 관리 정책을 통해 사용자는 브라우저를 닫았다가 다시 열어도 일정기간 로그인 상태가 유지되고 세션이 유효한 이상 로그인 상태를 유지할 수 있다. )

---

# 서버가 로그인한 사용자를 인식하는 방식

### Q1: 로그인한 사용자를 서버가 지속적으로 인식하기 위해 쿠키와 세션이 어떻게 사용되는지 설명하세요. (서버 딴에서 api 호출할 때마다 어떤 일이 일어나는지.)
1. **로그인 성공 후 세션 생성**
- 사용자가 로그인 요청을 통해 인증에 성공하면 세션을 생성하고, `JSESSIONID`와 같은 세션 ID를 클라이언트에게 쿠키로 전달한다.(따로 지정을 하지 않으면 해당 Cookie의 이름은 JSESSIONID라고 붙여지게 된다.) 이 쿠키는 클라이언트의 웹 브라우저에 저장되고, 이후 요청을 할 때 계속 서버로 보내게 된다.

2. **API 호출 시 서버 동작**
- 클라이언트가 API 호출할 때 마다 웹 브라우저는 이전에 받은 세션 쿠키 `JSESSIONID`를 HTTP 요청 헤더에 포함시켜 서버로 전송하게 된다. 그럼 서버는 세션 ID를 사용해 `SecurityContext`에서 사용자의 인증 정보를 찾아 API 요청을 처리하기도 하며, 권한 검사도 진행한다. 이를 통해 사용자가 로그인한 상태가 지속되면서 권한에 맞는 리소스에만 접근할 수 있도록 한다.
---

### Q2: 쿠키가 세션 기반 로그인에서 어떤 역할을 하는지 구체적으로 서술하고, 특히 세션 ID가 쿠키에 저장되어 클라이언트와 서버 간에 전달되는 과정에 대해 설명하세요.

- **세션 ID가 쿠키에 저장되어 클라이언트와 서버 간에 전달되는 과정**

1. **로그인 요청 처리와 인증**
- 사용자가 입력한 ID와 비밀번호가 `MemberService.login`을 통해 DB 값과 비교되어 인증된다. 인증에 성공하면 `MemberLoginResDto`를 통해 해당 사용자의 정보가 `MemberController.login` 메서드로 전달된다.

2. **세션 생성**
- `MemberController.login` 메서드에서 `request.getSession(true)`를 호출해 세션을 생성하거나 기존 세션을 가져오고, 이 세션은 서버에 유지되며 클라이언트의 브라우저에는 세션 ID가 쿠키로 저장된다.

3. **SecurityContext에 인증 정보 설정**
- `UsernamePasswordAuthenticationToken`을 통해 사용자의 인증 정보 및 권한 정보를 담은 `Authentication` 객체를 생성한 후 `SecurityContext`를 생성하여 생성된 `Authentication`을 보관한다.

4. **SecurityContext를 세션에 저장**
- `SecurityContextHolder`에 사용자의 인증 정보가 담긴 `SecurityContext`를 설정 후, 이를 세션에 저장한다. 세션에 저장된 `SecurityContext`를 통해 서버는 세션 ID로 사용자의 인증 상태를 계속 인식할 수 있다.


즉, 쿠키는 서버가 클라이언트를 식별할 수 있게 하는 세션 ID를 클라이언트에게 보내는 매개체 역할을 하며, 이후에 클라이언트가 서버에 요청을 보낼 때마다 쿠키는 HTTP 요청 헤더에 포함되어 서버로 전달된다. 서버는 전달받은 세션 ID와 저장된 세션 데이터를 비교해 클라이언트를 식별하고 인증 상태를 유지한다. 이러한 방식으로 쿠키는 클라이언트의 인증 상태를 유지하고, 사용자가 여러 페이지를 이동하거나 다시 방문할 때도 로그인 상태가 유지되도록 돕는 중요한 역할을 한다.

---

# 세션을 구현할 때 보안적으로 고려해야 할 부분

- **세션 고정 공격 방지**
- 세션 고정 공격은 악의적인 사용자가 특정 세션 ID를 미리 설정한 후, 이를 사용자가 사용하게 만들어 해당 세션에 접근하는 공격 방법으로 사용자는 로그인 후 세션 ID를 재발급해 이러한 세션 고정 공격을 방어해야 한다.
<br> Security 설정에서 `.sessionManagement().sessionFixation().changeSessionId()`를 통해 로그인할 때마다 새로운 세션 ID를 발급해 공격을 방어할 수 있다.


- **세션 타임아웃 설정**
- 세션을 무기한 보관하게 되면 메모리 누수와 세션 탈취 공격 가능성이 있다. 그렇기 때문에 일정 시간 활동이 없는 세션은 자동으로 만료시켜야 한다. `sessionManagement().maximumSessions()`를 통해 사용자가 로그아웃을 하지 않더라도 일정 시간 후 자동 로그아웃을 유도해 보안을 강화해야 한다.


- **CSRF 보호 활성화**
- CSRF(Cross Site Request Forgery) 공격은 사용자가 의도하지 않은 요청을 악용해 악의적인 행위를 유도하는 기법이다. CSRF 공격을 방지하려면 Spring Security의 `.csrf(csrf -> csrf.enable())`와 같이 CSRF 보호를 활성화해야 한다.