스프링 시큐리티를 활용하여 OAuth2.0 소셜로그인 구현하기
개발환경
- 스프링부트 3.2.2
- 스프링 시큐리티 6.2
- 타임리프, JPA, MariaDB, OAuth2.0
소셜로그인을 구현하기위해서 OAuth2.0 라이브러리를 사용하는데,
보통 JWT와 함께 사용하여 JWT토큰과함께 사용해서 소셜로그인 기능을 구현하지만
스프링 시큐리티 세션만을 이용해서 소설로그인 기능을 구현하였다.
OAuth2.0 소셜로그인 실행흐름
실행흐름을 크게 나누어보면,
1. 제일먼저 클라이언트가 네이버 로그인을 사용하기위해 해당 url로 요청을 보내면,
서버에서 네이버 로그인 인증을 시작하는 url 엔드포인트로 보낸다.
2. 사용자가 네이버 로그인화면에서 로그인에 성공하면, 네이버 로그인 api 신청하면서 미리 입력해둔 리다이렉트 url로 반환되며, 네이버에서 서비스 인증에 성공하였다는 code를 발급해준다.
3. 서버에서 해당 code를 가지고 Access 토큰을 발급받는다.
4. 서버에서 발급한 Access 토큰을 기반으로 네이버 서버에 요청을 보내, 사용자에 관한 정보를 얻는다.
5. 이후 OAuth2UserDetails 와 같은 객체에 사용자 정보를 저장하여 SecurityContextHolder와 같은 방식으로 세션에 담아놓고 사용한다.
의존성 추가
시큐리티 설정
해당 기능을 구현하면서 나는 기존의 시큐리티를 사용한 자체 로그인또한 같이 사용하고있었으므로
Security FilterChain에서 formlogin방식도 같이 사용하기위해 로그인 접근 url을 소셜로그인과 자체로그인 2가지로 나누었다.
따라서, 소셜로그인은 Oauth2Login 메소드를 타고 로그인 과정이 진행되며
자체로그인은 formLogin 메소드를 타고 진행된다.
네이버 로그인 API 인증정보 등록
다음과 같이 application.properties에 저장해놓고 사용해도 되지만,
추후 access토큰정보를 DB에 저장하기위해 따로 클래스를 만들어 리포지토리와 함께 메소드의 형태로 명시해주었다.
OAuth2User 구현
@Data
public class CustomOAuth2User implements OAuth2User {
public CustomOAuth2User(OAuth2Response oAuth2Response, String role,String userid,boolean enabled,String uname,String profileurl,boolean social) {
this.oAuth2Response = oAuth2Response;
this.userid = userid;
this.role = role;
this.enabled = enabled;
this.uname = uname;
this.profileurl = profileurl;
this.social = social;
}
private final OAuth2Response oAuth2Response;
private final String role;
private final String userid;
private Boolean enabled;
private String uname;
private String profileurl;
private String phone;
private Boolean social;
@Override
public Map<String, Object> getAttributes() {
return null;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return role;
}
});
return collection;
}
@Override
public String getName() {
return oAuth2Response.getName();
}
public String getUserName(){
return oAuth2Response.getProvider()+" "+oAuth2Response.getProvider();
}
}
스프링 시큐리티의 UserDetails와 유사하게 OAuth2에서 OAuth2User를 구현한 객체를 작성해준다.
네이버에서 인증에 성공하면, 해당 객체에 필요한 정보들을 담아서 보관하거나, UserDetails 객체로 복사해서
스프링 시큐리티 세션과 같이 사용할수도 있다.
CustomOAuth2UserService 구현
가장 중요한 메소드로 스프링 시큐리티의 UserDetailService와 같이 DefaultOAuth2UserService를 상속받아
소셜 로그인 이후 필요한 처리를 해주는 메소드이다.
즉, 소셜로그인에 성공한 이후 네이버 서버에서 코드를 보내주면 loadUser 메소드를 통해 OAuth2User 타입의 객체를 반환한다.
여기에서 access토큰을 발급받아 네이버에서 필요한 정보들을 api요청하여 OAuth2User 객체에 저장해주면 되지만
나의 경우에는 기존에 자체로그인을 구현한뒤 소셜로그인 기능을 추가한터라 기존에 구현된 자체로그인 항목과 부가기능들이 너무 방대해져 해당 로직내에서 OAuth2User 객체를 직접 세팅해주었다.
그리고 세팅된 OAuth2User를 기반으로 User 테이블에 등록해준뒤,
처음 소셜로그인한 회원이면 User테이블에 추가하는 방식으로 구현하였다.
이부분은 비즈니스 요구에 따라 변형해서 사용하면 될것같다.
해당 loadUser 메소드가 실행되면 Return으로 OAuth2User를 상속받아 구현한 CustomOAuth2User 객체가 생성된다.
그리고 해당 객체를 SecurityContextHolder에 넣어 기존 세션과 함께 사용하였다.
네이버 로그인 인증 엔드포인트에 접근하면 해당 화면이 나오고,
로그인을 하게되면, 필요한 최소정보를 기반으로
다음과 같이 DB에 User테이블에 소셜 로그인 유저또한 추가되어 User객체로 함께 관리하였다.
위 게시글은 해당 강의를 참고하여 개인적으로 공부하며 작성한 내용으로 실제와 다를수있습니다.
https://substantial-park-a17.notion.site/OAuth2-295f3799ed7f47dcabf537dce52ea9e7
'Category > Project' 카테고리의 다른 글
[개인프로젝트] 15일차 - 배열 탐색 (0) | 2024.03.02 |
---|---|
[개인프로젝트] 13일차 - 제이쿼리,자바스크립트 (0) | 2024.02.28 |
[개인프로젝트] 10일차 - JPA 페이징처리,검색기능 (0) | 2024.02.27 |
[개인프로젝트] 6일차 - JPA 다대다 테이블 매핑 순환참조 문제 (0) | 2024.02.22 |
[개인프로젝트] 5일차 - 카카오 주소 api를 사용해서 네이버 map api 표현하기 (0) | 2024.02.22 |