250x250
jhs0129
프로그래밍
jhs0129
전체 방문자
오늘
어제
  • 분류 전체보기
    • 자격증
      • SQLD
      • 정보처리기사
    • 프로젝트
      • html csss js - todolist
      • JSP 방명록
      • 졸업작품
    • 공부기록
      • Java
      • Spring
      • Spring Security
      • Algorithm
      • JPA
      • DB
      • Servlet JSP
      • html
      • 기술공유
    • 잡다한 생각

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Spring Security Login
  • 프로젝트
  • spring framework
  • github
  • spring data jpa
  • codedeploy
  • oAuth2
  • cicd
  • EC2
  • 스프링시큐리티
  • NHN Cloud
  • nhn cloud 강의
  • spring boot
  • spring
  • Spring Security
  • rest docs
  • AWS
  • JPA
  • 스프링
  • 스프링 프레임워크

최근 댓글

최근 글

티스토리

반응형
hELLO · Designed By 정상우.
jhs0129

프로그래밍

[추가] 스프링 시큐리티 OAuth 로그인 처리 방법 1
공부기록/Spring Security

[추가] 스프링 시큐리티 OAuth 로그인 처리 방법 1

2023. 2. 22. 12:00
320x100
반응형

목차

  • [이론] 스프링 시큐리티 1
  • [OAuth] 스프링 시큐리티 OAuth
  • [실습] 스프링 시큐리티 OAuth2 Login 1
  • [실습] 스프링 시큐리티 OAuth2 Login 2
  • [추가] 스프링 시큐리티 OAuth 로그인 처리 방법 1
  • [추가] 스프링 시큐리티 OAuth 로그인 처리 방법 2

이전에 스프링 시큐리티를 이용하여 OAuth로그인을 해보았다

정보를 매핑, 유저 저장하는 것 외에 단순히 yml파일에 정보만을 작성했을 뿐인데 로그인이 진행된 것을 볼 수 있다

크게 2가지 작업으로 나누어 어떻게 이루어 진것인지를 알아볼 예정이다

  1. Setting
  2. 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)
  • InMemoryClientRegistrationRepository Bean 등록

우선 첫번째 부터 확인 해보자

@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를 찾아 사용하게 되는것이다

정리

  1. application.yml을 통해 OAuth2ClientProperties 생성
  2. OAuth2ClientProperties를 가지고 ClientRegistration 리스트를 가진 InMemoryClientRegistratinoRepository bean으로 등록
320x100
반응형

'공부기록 > 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
    '공부기록/Spring Security' 카테고리의 다른 글
    • Spring Security - 동적 권한 처리
    • [추가] 스프링 시큐리티 OAuth 로그인 처리 방법 2
    • [실습] 스프링 시큐리티 OAuth2 Login 2
    • [실습] 스프링 시큐리티 OAuth2 Login 1
    jhs0129
    jhs0129
    공부기록 남기기

    티스토리툴바