forDevLife
[TIL]9/14(4일차) - Spring Boot Security + OAuth 본문
Spring Boot Security
- 스프링 부트는 인증과 권한에 관련된 강력한 기능인 '스프링 부트 시큐리티'를 제공한다. 이는 '스프링 시큐리티'의 번거로운 설정을 간소화시켜주는 래핑 프레임워크이다. (스프링 부트 시큐리티 = 스프링 시큐리티 + 스타터)
- 기본적인 틀 안에서 원하는 대로 인증, 권한 처리를 편하게 할 수 있다. 따라서 로직 구현에 집중할 수 있다.
- 일반적인 인증은 사용자명 / 비밀번호로 인증된다.
- 회원 가입 과정을 생략한 소셜 로그인 방식의 OAuth2도 활용할 수 있다. 이 방식으로 사용자 인증 후 각 사용자에게 허용되는 권한을 부여해볼 것이다.
- 스프링 부트 1.5 버전 기준으로 먼저 알아본 후, 2.0 버전으로 업그레이드를 해보자.
1. 배경 지식
- 스프링 부트 시큐리티에서 가장 중요한 개념은 인증(authentication)과 권한 부여(authorization) 이다.
- 인증 : 애플리케이션의 특정 동작에 관해 허락(인증)된 사용자인지 확인하는 절차 : 웹사이트 로그인
- 권한 부여 : 데이터 / 프로그램 등의 특정 자원이나 서비스에 접근할 수 있는 권한을 허용하는 것
- 인증 방식은 다양하다.
-. 크리덴셜 기반 인증 방식 : 전통적인 Id, password 기반 인증
-. 이중 인증 방식 : OTP 등의 추가 인증 방식을 도입해 한번에 2가지로 인증하는 방식
-. OAuth2 : 소셜 미디어 사용해 편리하게 인증하는 방식
2. OAuth2
- 토큰을 사용한 범용적인 방법의 인증을 제공하는 표준 인증 프로토콜이다. (OAuth 프로토콜 version 2)
- 서드파티(제 3자, 여기에서는 프로토콜이나 관련된 사항이 아닌 다른 리소스)를 위한 범용적인 인증 표준
- 제공하는 승인 타입은 총 4가지가 있다.
-. 권한 부여 코드 승인 타입(Authorization Code Grant Type) : 눈여겨볼 일반적인 방식(구글 / 페이스북 / 카카오)
-> 클라가 다른 사용자 대신 특정 리소스에 접근 요청시 사용한다. 리소스 접근을 위한 사용자명 / 비밀번호, 권한 서버에서 받은
권한 코드를 함께 활용하여 리소스에 대한 액세스 토큰을 받으면 이를 인증에 활용.
-. 암시적 승인 타입(Implicit Grant Type) : 아래 그림에서 추가 설명 참고
-> 권한 부여 코드 승인 타입과 다르게 권한 코드 교환 단계 없이 액세스 토큰을 즉시 반환받아 인증에 이용하는 방식
-. 리소스 소유자 암호 자격 증명 승인 타입(Resource Owner Password Credentials Grant Type)
-> 클라가 암호를 사용하여 액세스 토큰에 대한 사용자의 자격 증명을 교환하는 방식
-. 클라이언트 자격 증명 승인 타입(Client Credentials Grant Type)
-> 클라가 컨텍스트 외부에서 액세스 토큰을 얻어 특정 리소스에 접근을 요청할 때 사용하는 방식
- 권한 부여 코드 승인 타입 방식은, 웹 서버에서 장기 액세스 토큰(long-lived access token)을 통해 사용자 인증을 처리한다.
- 리소스 주인 : 예) 인증이 필요한 사용자
- 클라이언트 : 예) 웹사이트
- 권한 서버 : 예) 페이스북 / 구글 / 카카오 서버
- 리소스 서버 : 예) 페이스북 / 구글 / 카카오 서버
1) 클라이언트가 파라미터로 클라 id, redirect uri, 응답 타입을 code로 지정하여 권한 서버에 전달한다. 정상적으로 인증이 되면 권한 부여 코드를 클라이언트에 보낸다.(응답 타입은 code, token 사용 가능, token일 때가 암시적 승인 타입)
2) 성공적인 권한 부여 코드를 받은 클라는 이를 사용해서 *액세스 토큰을 권한 서버에 추가 요청한다. 이 때 필요한 파라미터는 클라 id, 비밀번호, redirect uri, 인증 타입이다.
(*액세스 토큰 : 로그인 세션에 대한 보안 자격을 증명하는 식별 코드이다. 권한 및 경우에 따라 특정 API 사용을 보증하는 역할)
3) 마지막으로 응답받은 액세스 토큰을 이용하여 리소스 서버에 사용자의 데이터를 요청한다.(API 호출)
- 사용자명 + 비밀번호 방식은 저장된 사용자명 / 비밀번호가 같은지 한 번만 요청하면 되지만, OAuth2 방식은 최소 3번 요청한다.
하지만 회원가입 없이 이미 사용하는 소셜 미디어 계정으로 인증하기 때문에 사용자 입장에서는 더욱 편리하게 로그인을 처리할 수 있다.
서비스 측면에서는 회원 가입 관련 기능 축소시키고, 소셜에서 제공하는 User 정보를 가져올 수 있어 편리하다.
- 정리하면, 1) 권한 부여 코드 요청 및 응답 -> 2) 액세스 토큰으로 교환 요청 및 응답 -> 3) 토큰을 사용한 API 호출 및 응답
3. 스프링 부트 시큐리티 + OAuth2 설계하기
1) 사용자가 애플리케이션에 접속하면 해당 사용자에 대한 이전 로그인 정보(세션)의 유무를 체크한다.
2) 세션이 있으면 그대로 세션을 사용하고, 없으면 OAuth2 인증 과정을 거치게 된다.
3) 이메일을 키 값으로 사용해서 이미 가입된 사용자인지 체크한다. 이미 가입되었다면 등록된 정보를 반환하여 요청한 URL로의 접근을 허용하고, 아니면 새롭게 User 정보를 저장하는 과정을 진행한다.
4) 각 소셜 미디어에서 제공한 User 정보가 다르기 때문에 소셜 미디어에 따라 User 객체를 생성한 후 DB에 저장한다.
* 세션이 있거나 4번까지 성공한 사용자는 요청한 URL로의 접근을 허용한다.
- 각 소셜 미디어 타입을 갖고 있는 SocialType 객체 생성(Enum type)
public enum SocialType {
FACEBOOK("facebook"),
GOOGLE("google"),
KAKAO("kakao");
private final String ROLE_PREFIX = "ROLE_";
private String name;
SocialType(String name) {
this.name = name;
}
public String getRoleType() {
return ROLE_PREFIX + name.toUpperCase();
}
public String getValue() {
return name;
}
public boolean isEquals(String authority) {
return this.getRoleType().equals(authority);
}
}
- getRoleType을 통해 'ROLE_*' 형식으로 소셜 미디어의 권한명을 생성한다.
- enum을 사용해 권한 생성 로직을 공통 코드로 처리하여 중복 코드를 줄일 수 있다.
- principal : OAuth2 인증으로 제공받는 키 값
- socialType : 어떤 소셜미디어로 인증받았는지 여부를 구분
4. 스프링 부트 시큐리티 + OAuth2 의존성 설정하기
'각종 회고' 카테고리의 다른 글
[TIL]9/15 - AOP (0) | 2021.09.29 |
---|---|
[TIL]9/15(5일차) - WEB2 : OAuth 2.0 (0) | 2021.09.15 |
[TIL]9/13(3일차) (0) | 2021.09.13 |
[TIL] 9/10 (2일차) (0) | 2021.09.10 |
[TIL] 9/9 (1일차) (0) | 2021.09.09 |