2025. 2. 18. 17:37ㆍSpringboot/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