Spring Security session방식 OAUTH2로그인 - 동작방식(1)

2025. 2. 18. 17:37Springboot/security

기본적인 oauth2 로그인 설명은 카카오를 기본으로 설명합니다. 

동작방식의 각 동작에서 주소등은  설정파일들에서 설정하는 내용입니다.

 

 

 

동작방식 

1. 로그인버튼  클릭

카카오 로그인버튼 a태그의 href는  localhost:8080:/oauth2/authorization/kakao 고정이다.

security에서 localhost:8080:/oauth2/authorization/{registartionId}를 이용해 처음 oauth2로그인과정을 시작.

{registartionId}는  application.yml파일 설정에 따라 security가 인식한다.

security :
  oauth2:
    client:
      registration:  
        kakao:

 

 

우리 서버는 브라우저한테  응답코드 302로 응답합니다. (redirect)

redirect 할 주소는 

authorization-uri: https://kauth.kakao.com/oauth/authorize

 

 

 

2.   카카오 인증 서버로 요청 

redirect를 받았기 때문에 브라우저는 바로 

https://kauth.kakao.com/oauth/authorize?response_type=code &client_id=YOUR_KAKAO_REST_API_KEY &redirect_uri=http://localhost:8080/login/oauth2/code/kakao &scope=profile_nickname,account_email &state=xyz123 

로 요청한다.

이 때   파라미터에 있는 redirect-uri는 다음과 같고, 이 값을 카카오서버가 기억하게 된다.

redirect-uri:   http://localhost:8080/login/oauth2/code/kakao  # 카카오로그인 후 우리서버에서 로그인하기 위한주소. (카카오devloper랑 일치)

 

 

 

 

 

 3.  카카오로그인페이지에서 ID, PW입력

카카오로그인 페이지에서 카카오 ID, PW를 입력한다.

성공하면 카카오인증서버로부터  응답코드302의 response를 받는다.

이 때 redirect 주소는 아까 2번 과정의  redirect-uri.

또 response에  인가코드가 포함된다.

 

참고로 인가코드가 포함되는 이유는 인가코드 방식으로 설정했기때문에.

authorization-grant-type: authorization_code

 

 

 

 

 

4.  redirect-uri로 요청   

redirect-uri:   http://localhost:8080/login/oauth2/code/kakao 

 

카카오에서는 로그인 성공해서 인가코드를 준 상태이고

브라우저는 인가코드를 포함해 redirect-uri로 우리서버에 요청한다.

 

이제  우리서버에서 로그인을 진행하게 된다.

이후 과정은 재요청은 없고 현재 요청진행 과정 중 로그인 과정을 설명한다.

 

 

5.  로그인과정

이미 카카오서버에서는 로그인성공한거고 그 결과로 요청에 인가코드가 포함된 상태이다.

우리서버는 우리서버에서의 로그인(유저정보가 필요한데 카카오에 있음)을 위해 

인가코드 => access_token(userRequest)                         (security가 알아서)

=>  유저정보를 획득한 후 우리서버에 맞게 로그인유저정보를 만든다.  (개발자가 구현)

 

여기서  토큰요청 주소와  유저정보 요청주소는 다음과 같다.

token-uri: https://kauth.kakao.com/oauth/token
user-info-uri: https://kapi.kakao.com/v2/user/me

 

 

 

security 기본로그인과정과 비교해 보면

UserDetails를 이용해 로그인판단을 하지 않는다.  

로그인판단 여부는 카카오가 이미 했기때문.

 

 

 

 

 

 

6. 세션 저장.

우리서버에 맞는 유저정보를 

session에 저장합니다.  (security 기본과 동일) 

 

 

 

※ 카카오 공식 로그인프로세싱 이미지 이해하기.

https://developers.kakao.com/docs/latest/ko/kakaologin/common에 있는 이미지이다.

빨간줄은 생략된 부분.

 

공식이미지에서는 웹 환경뿐만 아니라 여러환경에서의 사용을 고려해 생략하였지만,

웹 환경에서는 브라우저가 직접 redirect를 진행하기 때문에 빨간줄과 같은 과정이 있는거다.

1~6까지의 과정을 잘 이해했다면 공식이미지의 과정도 잘 이해할 수 있을거다.

 

 

 

 

 

프로젝트 세팅

Spring Data JDBC,H2 Database,  Spring Data JPA,  Spring Web, Thymeleaf,

Spring Boot Devtools ,  Lombok,  Spring security  , Oauth2

입니다.

 

 

 

 

SecurityConfig

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    @Bean
    public PasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }


    private final CustomUserDetailsService customUserDetailsService;
    private final CustomOAuth2UserService customOAuth2UserService;


    @Bean
    public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception{
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/h2-console/**").permitAll() // H2 콘솔 접근 허용
            )
            .csrf(csrf -> csrf.ignoringRequestMatchers("/h2-console/**")) // H2 콘솔 CSRF 비활성화
            .headers(headers -> headers.frameOptions(frame -> frame.disable())); // H2 콘솔을 iframe에서 허용
        // 이 설정은 내부 H2DB 사용을 위한 설정일뿐 의미없음.


        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/images/**").permitAll()  // image 정적 자원 허용
            );


        http.authorizeHttpRequests((auth) -> auth
            .requestMatchers("/join/**", "/login").permitAll()
            .requestMatchers("/admin").hasAuthority("ADMIN")
            .requestMatchers("/my/**").hasAnyAuthority("ADMIN", "USER")
            .anyRequest().authenticated()
        );

        http.formLogin(auth -> auth
            .loginPage("/login")
            .loginProcessingUrl("/loginProc")  //기본값은 /login  (POST방식)
            .defaultSuccessUrl("/")
            .failureUrl("/login?error=true") // 로그인 실패 시 다시 로그인 페이지로.  기본값이 /login?error 지만  명시적으로.
            .permitAll()
        );

        
        http.userDetailsService(customUserDetailsService); //명시적으로 등록. 일반 form 로그인사용자처리

        http.oauth2Login(oauth2 -> oauth2
            .loginPage("/login")       // 한 페이지에서 폼 카카오 다 할거면 form이랑 같은게 좋음
            .defaultSuccessUrl("/") // 로그인 성공 후 이동할 URL
            .userInfoEndpoint(userInfo -> userInfo
                .userService(customOAuth2UserService) // 명시적.   OAuth2 사용자 로그인 처리
            )
        );
        http.logout((auth) -> auth.logoutUrl("/logout")
            .logoutSuccessUrl("/"));

        http.csrf((auth) -> auth.disable());   //csrf 적용X
        return http.build();
    }
}

 

 

 

application.yml

dotenv:
  enabled: true  # .env파일설정.    KAKAO_CLIENT_ID 직접 쓰려면 없어도됨.
spring:
  datasource:
    url: jdbc:h2:mem:security
    driver-class-name: org.h2.Driver
    username: sa
    password:
  h2:
    console: # H2 DB를 웹에서 관리할 수 있는 기능
      enabled: true           # H2 Console 사용 여부
      path: /h2-console       # H2 Console 접속 주소
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        default_batch_fetch_size: 100
    open-in-view: false
  devtools:
    livereload:
      enabled: true
    freemarker:
      cache: false
    restart:
      enabled: true
  thymeleaf:
    cache: false


  security:
    oauth2:
      client:
        registration:
          kakao:
            client-id: ${KAKAO_CLIENT_ID}  # 카카오 REST API 키
            #client-secret: ${KAKAO_CLIENT_SECRET}  # 선택 (일반적으로 필요 없음)
            redirect-uri: http://localhost:8080/login/oauth2/code/kakao # 카카오 로그인 후 리디렉트될 주소. 카카오개발자센터의 값이랑 동일
            authorization-grant-type: authorization_code  # OAuth2 인증 방식 (코드 방식)
            scope:
             - profile_nickname
             - account_email  # 요청할 사용자 정보 (이메일, 닉네임)


        provider:
          kakao:
            authorization-uri: https://kauth.kakao.com/oauth/authorize  # 카카오 로그인 URL  (인증서버)
            token-uri: https://kauth.kakao.com/oauth/token  # 액세스 토큰 요청 URL (인증서버)
            user-info-uri: https://kapi.kakao.com/v2/user/me  # 사용자 정보 요청 URL (리소스서버)
            user-name-attribute: id  # OAuth2User에서 사용할 식별 값. 왠만하면 oauth에서 제공하는대로사용하자. 카카오는 id, 구글은 sub
logging:
  level:
    org.hibernate.SQL: debug
    org.hibernate.type: trace