목차
- [이론] 스프링 시큐리티 1
- [OAuth] 스프링 시큐리티 OAuth
- [실습] 스프링 시큐리티 OAuth2 Login 1
- [실습] 스프링 시큐리티 OAuth2 Login 2
- [추가] 스프링 시큐리티 OAuth 로그인 처리 방법 1
- [추가] 스프링 시큐리티 OAuth 로그인 처리 방법 2
이전에 스프링 시큐리티를 이용하여 OAuth로그인을 해보았다
정보를 매핑, 유저 저장하는 것 외에 단순히 yml파일에 정보만을 작성했을 뿐인데 로그인이 진행된 것을 볼 수 있다
크게 2가지 작업으로 나누어 어떻게 이루어 진것인지를 알아볼 예정이다
- Setting
- Login 요청 처리
양이 좀 많으므로 우선 Setting부분을 알아보자
Setting
프로퍼티객체 생성
스프링은 기본적으로 수 많은 자동 설정들을 제공한다org.springframework.boot.autoconfigure.AutoConfiguration.imports를 보게되면 144개나 되는 자동 설정정보들이 들어있는 것을 확인 할 수 있다
그 중 하나인 OAuth2ClientAutoConfiguration가 yml(혹은 properties)파일에 작성한 내용을 기반으로 registration과 provider를 등록을 해준다
@AutoConfiguration(before = SecurityAutoConfiguration.class)
@ConditionalOnClass({ EnableWebSecurity.class, ClientRegistration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@Import({ OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class })
public class OAuth2ClientAutoConfiguration {
}
@Import에 OAuth2ClientRegistrationRepositoryConfiguration.class를 타고 들어가면 다음과 같은 코드를 볼 수 있다
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(OAuth2ClientProperties.class)
@Conditional(ClientsConfiguredCondition.class)
class OAuth2ClientRegistrationRepositoryConfiguration {
@Bean
@ConditionalOnMissingBean(ClientRegistrationRepository.class)
InMemoryClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {
List<ClientRegistration> registrations = new ArrayList<>(
OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties).values());
return new InMemoryClientRegistrationRepository(registrations);
}
}
이 중 우리는 두가지를 눈여겨 볼 필요가 있다
@EnableConfigurationProperties(OAuth2ClientProperties.class)InMemoryClientRegistrationRepositoryBean 등록
우선 첫번째 부터 확인 해보자
@EnableConfigurationProperties(OAuth2ClientProperties.class)
OAuth2ClientProperties 객체를 Property 파일을 통해 생성을 가능하게 해주는 것이다
- OAuth2ClientProperties.class
보기 쉽게 메소드는 모두 제거를 했다
우리가 작성했단 application-oauth.yml과 비교를 해보자
@ConfigurationProperties(prefix = "spring.security.oauth2.client")
public class OAuth2ClientProperties implements InitializingBean {
private final Map<String, Provider> provider = new HashMap<>();
private final Map<String, Registration> registration = new HashMap<>();
public static class Registration {
private String provider;
private String clientId;
private String clientSecret;
private String clientAuthenticationMethod;
private String authorizationGrantType;
private String redirectUri;
private Set<String> scope;
private String clientName;
}
public static class Provider {
private String authorizationUri;
private String tokenUri;
private String userInfoUri;
private String userInfoAuthenticationMethod;
private String userNameAttribute;
private String jwkSetUri;
private String issuerUri;
}
}
spring:
security:
oauth2:
client: # 이 부분까지 Prefix
registration: # 내부 static class인 Registration
google:
client-id:
client-secret:
redirect-uri: http://localhost:8080/login/oauth2/code/google
scope: email, profile
naver:
client-name: naver
client-id:
client-secret:
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login/oauth2/code/naver
provider: # 내부 static class인 Provider
naver:
authorization-uri: https://nid.naver.com/oauth2.0/authorize
token-uri: https://nid.naver.com/oauth2.0/token
user-info-uri: https://openapi.naver.com/v1/nid/me
user-name-attribute: response
딱 봐도 비슷한 구조를 가진 것을 알 수 있다
@ConfigurationProperties 애노테이션은 우리가 설정 파일에 적어준정보를 객체 필드에 주입해여 생성해 준다
위 파일로 예시를 들면 registration에 google, naver를 key로 하위 값들을 value로 주입하는 것이다
InMemoryClientRegistrationRepository Bean 등록
다음으로는 위 설정 값인 OAuth2ClientProperties를 가지고 ClientRegistrationRepository를 등록하는것을 확인 해보자
- OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties)
public static Map<String, ClientRegistration> getClientRegistrations(OAuth2ClientProperties properties) {
Map<String, ClientRegistration> clientRegistrations = new HashMap<>();
properties.getRegistration().forEach((key, value) -> clientRegistrations.put(key,
getClientRegistration(key, value, properties.getProvider())));
return clientRegistrations;
}
private static ClientRegistration getClientRegistration(String registrationId,
OAuth2ClientProperties.Registration properties, Map<String, Provider> providers) {
Builder builder = getBuilderFromIssuerIfPossible(registrationId, properties.getProvider(), providers);
if (builder == null) {
builder = getBuilder(registrationId, properties.getProvider(), providers);
}
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
//매핑 작업
return builder.build();
}
getBuilderFromIssuerIfPossible()메소드는 우리가 yml 설정 파일에 직접 작성한 provider(naver)를 통해서 ClientRegistration.Builder를 생성해준다
google과 같이 직접 작성하지 않은 Provider는 null을 반환하여 getBuilder()를 타고 들어가 보면 아래와 같은 코드를 보게 된다
이 메소드에서 ProviderId(naver, google, github)를 통해서 CommonOAuth2Provider객체를 얻어온다
private static CommonOAuth2Provider getCommonProvider(String providerId) {
try {
return ApplicationConversionService.getSharedInstance().convert(providerId, CommonOAuth2Provider.class);
}
catch (ConversionException ex) {
return null;
}
}
CommonOAuth2Provider는 Spring Security에서 미리 등록해준Provider이다
우리가 yml파일에 google과 달리 naver에서 많은 정보를 적어준 이유가 Spring Security가 제공을 해주지 않기 때문이다

이렇게 yml에 적어준 registration을 통해 ClientRegistration이 생성되고 해당 객체 리스트를 값으로 InMemoryClientRegistratinoRepository가 bean으로 등록되어 로그인 요청 시 InMemoryClientRegistratinoRepository에서 ClientRegistration를 찾아 사용하게 되는것이다
정리
- application.yml을 통해
OAuth2ClientProperties생성 OAuth2ClientProperties를 가지고ClientRegistration리스트를 가진InMemoryClientRegistratinoRepositorybean으로 등록
'공부기록 > Spring Security' 카테고리의 다른 글
| Spring Security - 동적 권한 처리 (2) | 2023.03.29 |
|---|---|
| [추가] 스프링 시큐리티 OAuth 로그인 처리 방법 2 (0) | 2023.02.22 |
| [실습] 스프링 시큐리티 OAuth2 Login 2 (2) | 2023.02.21 |
| [실습] 스프링 시큐리티 OAuth2 Login 1 (0) | 2023.02.21 |
| [이론] 스프링 시큐리티 OAuth (0) | 2023.02.20 |