로그인 관련 코드를 작성하다보면 회원가입 -> 로그인 순으로 코드를 작성하는데
정작 나는 기본 로그인을 한적이 없다는걸 깨달았습니다.
그래서 이번 기회에 카카오,구글 로그인등 SNS 로그인을 공부해 보려고 합니다
목차
1. 시큐리티의 기본흐름은 어떻게 되는가?
2. SNS 로그인의 절차는 무엇인가?
3. 코드 분석
여러 블로그 찾으면 다 있는 그림인데 이 보다 간단한건 없었습니다.
이 부분은 그렇구나 하고 넘어가면 됩니다 지금 이해 못합니다
우선 1번은 사용자가 요청하는 것을 의미합니다 간단하죠? 2번부터 힘들어집니다.
2번 - AuthenticationFilter 에서 UsernamePasswordAuthenticationToken 을
만드는 과정을 거치게 됩니다.
3번- 만들어진 토큰을 AuthenticationManager 에게 넘겨주게 됩니다.
4번- 그러면 AuthenticationManager 가 AuthenticationProvider 에게 넘겨줍니다.
5번- AuthenticationProvider 에서는 UserDetailsService 를 호출하여 UserDetails 를 가져오게 됩니다.
6 ~ 10번 - 인증된 사용자 정보를 저장합니다
결론: 토큰을 만들어 왔다갔다 한다
결론만 기억합시다
Resource Owner
웹 서비스를 이용하려는 유저
Client (현재 우리가 개발중인 서버)
자사 또는 개인이 만든 애플리케이션 서버
클라이언트 라는 이름은 client가 Resource server에게 필요한 자원을 요청하고 응답하는 관계여서 그렇다.
Authorization Server
권한을 부여 해주는 서버다. 사용자는 이 서버로 ID, PW를 넘겨 Authorization Code를 발급 받을 수 있다. Client는 이 서버로 Authorization Code을 넘겨 Token을 받급 받을 수 있다.
Resource Server
Google, Facebook, Kakao 등 회사 서버. Client는 Token을 이 서버로 넘겨 개인정보를 응답 받을 수 있다.
Access Token
자원에 대한 접근 권한을 Resource Owner가 인가하였음을 나타내는 자격증명
절차가 복잡해 보이지만 다 구현할 필요없이 시큐리티에서 알아서 Authorization Code 발급받고 Access Token 받아오고 사용자 정보를 요청해서 가져오기 때문에
우리가 구현할 부분은 2번이랑 13번 에서 넘어온 사용자 정보 저장하는일 밖에 없습니다
우선 SecurityConfig 먼저 살펴보겠습니다.
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final AuthenticationProvider authenticationProvider;
private final AuthenticationFailureHandler authenticationFailureHandler;
private final AuthenticationSuccessHandler authenticationSuccessHandler;
private final AccessDeniedHandler accessDeniedHandler;
private final AuthenticationConfiguration authenticationConfiguration;
private final AuthenticationManagerBuilder authenticationManagerBuilder;
private final CustomOAuth2UserService customOAuth2UserService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// AuthenticationFilter 설정정보
CustomAuthenticationFilter customAuthenticationFilter =
new CustomAuthenticationFilter(authenticationManager(authenticationConfiguration,authenticationManagerBuilder));
customAuthenticationFilter.setFilterProcessesUrl("/login"); // /login 요청시 AuthenticationFilter 가서 처리를 합니다.
customAuthenticationFilter.setPostOnly(true); // 항상 POST 처리
customAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler); // 성공시 핸들러 설정
customAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler); // 실패시 핸들러 설정
http.csrf().disable(); // POST 가능하게 설정
http.authorizeRequests() // 인증이 된 경우에만 접근을 허용하는데
.anyRequest() // 인증된 어떤 요청이든 오던지
.permitAll() // 허용하라.
.and() // 또한
.oauth2Login() // 소셜로그인을 진행하는데
.successHandler(authenticationSuccessHandler) //성공하면 커스텀한 핸들러에서 처리한다
.userInfoEndpoint() // 사용자 정보를 가져올 때
.userService(customOAuth2UserService); // 커스텀한 서비스에서 정보를 처리한다
http.addFilter(customAuthenticationFilter); // AuthenticationFilter 추가
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 예외처리 핸들러 설정
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration
,AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider); //authenticationProvider 를 설정합니다
return authenticationConfiguration.getAuthenticationManager(); // AuthenticationManager 정보를 가져옵니다
}
}
더 이상 WebSecurityConfigurerAdapter 는 지원하지 않기 때문에 과감하게 다 빼버리고 새롭게 권장하는 방식으로 진행했습니다.
SecurityFilterChain 에서 설정정보를 등록할 수 있습니다.
우선 SNS 로그인부터 설명하겠습니다.
1번 .oauth2Login()
2번 .successHandler(authenticationSuccessHandler)
3번 .userInfoEndpoint()
4번 .userService(customOAuth2UserService);
1~4 에서 소셜로그인이 처리 됩니다.
1,2 번은 소셜로그인을 시작하고 성공하면 이렇게 처리 하겠다는 의미이고
3,4 번은 앞서 말한 13번에 해당하는 부분입니다.
나머지 부분은 일단 신경 안써도 됩니다.
<a href="/oauth2/authorization/google">구글 아이디로 로그인</a>
<a href="/oauth2/authorization/kakao">카카오 아이디로 로그인</a>
<a href="/oauth2/authorization/naver">네이버 아이디로 로그인</a>
위 링크는 소셜로그인을 진행할수 있는 링크 입니다
/oauth2/authorization/서비스이름 형태로 되어있고 고정입니다
oauth2앞 부분은 로컬이면 localhost:8080 이고 서비스 중인 서버에서는
도메인명/oauth2 ~ 이렇게 바뀝니다.
위 링크를 누르면
또는
로그인 창이 나오게 됩니다 SNS 흐름 4번에 해당하는 부분입니다. 로그인을 진행하면 13번까지 알아서 진행하게 됩니다. 간단하죠?
13번이 끝나면 .userService(customOAuth2UserService); 에 있는 customOAuth2UserService를 통해 사용자 정보를 저장만 하면 됩니다.
사용자 정보는 이미 넘어온 상태입니다. 요청할 필요 없습니다.
다음 글에서 customOAuth2UserService 를 살펴보겠습니다.
오 매우 유익해요! 이해가 쏙쏙 되었습니다