diff --git a/keyword/chapter10/keyword.md b/keyword/chapter10/keyword.md new file mode 100644 index 0000000..4758c04 --- /dev/null +++ b/keyword/chapter10/keyword.md @@ -0,0 +1,217 @@ +- **Spring Security** + + + - 스프링에 기반해서 인증과 인가를 담당하는 보안 프레임워크이다 + + - 스프링 MVC와 분리되어 있어 보안과 관련된 부분과 비즈니스 핵심 로직을 구분해서 사용할 수 있다 + + 흐름 + + 1. 사용자가 로그인과 관련된 정보를 가지고 인증 요청을 한다 + + 2. 유저 자격을 바탕으로 인증 토큰을 생성한다 + 1. AuthenticationFilter이 요청을 가져가고 이를 통해 UsernamePasswordAuthenticationToken 의 인증용 토큰 생성 + + 3. Filter 를 이용해서 인증 토큰을 AuthenticationManager로 위임한다 + + 4. AuthenticationProvider 의 목록들을 조회하며 인증을 시도한다 + + 5. 실제 데이터베이스에서 사용자 인증 정보를 가져오는 UserDetailsService에 사용자 정보를 넘겨준다 + + 6. 받아온 사용자 정보를 통해 UserDetails 객체를 생성한다 + + 7. 사용자의 정보를 비교한다 + + 8. 인증이 끝나면 사용자 정보를 담은 Authentication 객체를 반환한다 + + 9. 끝 + + 주요 컴포넌트 + + - SecurityContextHolder + - 가장 밖에 있는 컨테이너 + - 현재 실행중인 스레드의 SecurityContext를 보관하는 곳 + - static 클래스이다 + - 어디에서든 현재 로그인 사용자 정보에 접근 할 수 있다 + + - SecurtiyContext + - 현재 요청에 대한 보안 상태를 담아둔다 + - 인증이 성공할 경우 생성 + + - Authentication + - 해당 사용자가 누구고 어떤 권한을 가졌는지를 표현한다 + + + + +- **인증(Authentication)과 인가(Authorization)** + + + 인증 + + - 해당 사용자가 본인이 맞는지 확인하는 과정 + - 요청 초기 필터 단계에서 일어난다 + - 인증이 성공할시 + - 사용자에 대한 정보가 담긴 Authentication 객체가 생성된다 + - 인증이 실패한 경우 + - 401 답변이 주로 반환된다 + + 인가 + + - 해당 사용자가 특정 리소스에 접근이 가능한지를 판단 + - 당연하게도 인증 이후에 인가가 수행된다 + - 인가가 성공한 경우 + - 해당 리소스를 볼 수 있게 된다 + - 인가에 실패한 경우 + - 403 응답을 반환한다 + - 인가의 종류 + - url 단위 + - /admin/** + - 메서드 단위 + - @PreAuthorize + + + + +- **세션과 토큰** + + + - 세션 + - 서버가 사용자의 로그인 상태를 기억한다 + - 로그인에 성공한 경우.. + - 서버가 해당 사용자에 대한 세션을 생성 + - 이를 서버 메모리나 세션 저장소에 보관한다 + + - 클라이언트 + - 세션을 식별하는 세션 ID를 쿠키로 가져간다 + - 모든 요청에 세션 ID 를 제공하고 서버는 이를 확인한다 + + - 대체적으로 서버의 부담이 보다 큰 구조이다 + + - 세션 공유 문제가 발생할 수도 있다 + - 사용자 세션이 특정 서버에만 존재해 다른 서버에서는 해당 사용자의 로그인 상태를 알 수 없는 문제 + + - 구현이 토큰 방식보다는 간편하고 직관적이다 + + + + 세션기반 흐름 + + 1. 사용자가 아이디와 비번을 전송하다 + 2. 서버에서 검증한다 + 3. 서버가 세션을 만든다 + 4. 세션 ID를 만든다 + 5. 이를 쿠키로 클라이언트에게 준다 + + 이후… + + 1. 클라이언트가 쿠키에 세션 ID 도 같이 준다 + 2. 서버가 세션 저장소에서 맞는지 조회한다 + 3. 맞는 경우 해당 요청을 처리한다 + + + 세션 공유 문제 + + - 사용자 세션이 특정 서버에만 존재해 다른 서버에서는 해당 사용자의 로그인 상태를 알 수 없는 문제 + + - 상황 예시 + - 클라이언트, 로드 밸런서, 서버 A , 서버 B 가 있다고 가정 + + 1. 사용자가 로그인을 할때 서버 A로 요청 전달 + 2. 서버A가 세션을 생성한다 + 3. 이후 요청이 서버 B 로 들어간다 + 4. 서버B 는 해당 세션에 대해서 알지 못한다 + 5. 따라서 인증이 실패하게 된다 + + + + - 해결 방법 + 1. Sticky Session + 1. 같은 사용자를 항상 같은 서버에 보낸다 + - 단점 + - 특정 서버에 장애가 나면 해당 세션에 대한 자료가 사라질 수 있다 + - 확장성이 낮아진다 + + 1. 세션 클러스팅 + 1. 세션을 공용 저장소에 둔다 + - 단점 + - 인프라가 복잡해진다 + - 비용이 증가한다 + + → 이로 인해 토큰 방식이 나타났다 + + + + + - 토큰 기반 인증 + - 세션과 달리 서버가 로그인 상태를 기억하지 않는다 + - 사용자가 인증에 성공하면… + - 서버가 사용자 정보를 참고해 토큰을 만들고 클라이언트에게 전달한다 + - 해당 토큰은 서명이나 암호화 정보를 포함한다 + - 클라이언트는 다음 부터 이 토큰을 서버로 전달한다 + - 장점 + - 서버가 사용자의 상태를 저장하지 않는 무상태성을 가진다 + - 서버가 세션 공유 문제가 발생하지 않는다 + - 수평확장이 보다 간편하다 + - 단점 + - 구현이 세션 기반 보다는 복잡하다 + - 토큰의 만료기간 까지 해당 토큰이 유효하여 권한회수에 즉각적으로 대처하기 어렵다 + + + +- **액세스 토큰(Access Token)과 리프레시 토큰(Refresh Token)** + + + - 토큰 기반으로 구현을 하게 되면 토큰 탈취가 일어 날 수 있다!! + - 토큰이 한번 유출되면 해당 토큰이 만료되기 전까지는 계속 사용가능 하다 + + 이를 해결하는 방법은 액세스 토큰과 리프레시 토큰을 사용하는것이다 + + + - 엑세스 토큰 + - 실제 api를 요청할 때 사용하는 토큰이다 + - 만료 시간이 짧은 편이다 + - 탈취될 가능성이 비교적 높다 + - 만료시간이 짧은 이유 + + - 리프레시 토큰 + - 엑세스 토큰이 만료되면 새로운 엑세스 토큰을 받기 위한 토큰이다 + - api 요청에서는 사용되지 않는다 + - 토큰 재발급 요청에만 쓰인다 + - 만료시간이 길다 + - 외부레 비교적 노출이 적다 + - 탈취될 가능성이 낮다 + + + + 사용 흐름 + + 1. 로그인 + 1. 사용자가 로그인 시도한다 + 2. 서버에서 인증 완료 + 3. 엑세스 토큰과 리프레시 토큰을 만든다 + 4. 이를 클라이언트에게 준다 + + 1. api 요청이 온다 + 1. 클라이언트는 여기서 엑세스 토큰을 같이 준다 + 2. 서버가 이를 확인한다 + 3. 검증 완료시 요청을 처리한다 + + 1. 엑시스 토큰이 만료된 경우 + 1. 서버가 “야 엑세스 토큰 만료다!!!” 알려준다 + 2. 클라이언트가 이를 받고 리프레시 토큰을 서버에게 준다 + 3. 서버는 이 리프레시 토큰이 맞는지 검증한다 + 4. 맞다면 새로운 엑세스 토큰을 발급해서 준다 + + + 여기서 리프레시 토큰은 서버에 저장한다 + + 원인 + + - 강제 로그아웃 구현시 필요 + - 탈취 의심시 차단 + - 토큰 재사용 가능성을 방지 + + 엑세스 토큰은 이와 달리 서버에 저장하지 않는다 + + - 무상태성을 유지한다 \ No newline at end of file