Spring Boot 게시판 OAuth 2.0 네이버 로그인 구현
by coco3o이전 게시글에 이어서 네이버 OAuth 2.0 로그인을 구현하도록 하자.
Spring Boot 게시판 OAuth 2 구글 로그인 구현
Spring Boot에 Spring Security와 OAuth2.0을 사용해 소셜 로그인을 구현해보도록 하자. 1. 구글 OAuth 서비스 등록 필자는 이미 만들어놓은 프로젝트가 있어 예시 프로젝트를 하나 생성해보도록 하겠다. 1-1.
dev-coco.tistory.com
1. 네이버 OAuth 서비스 등록
필자는 이미 만들어놓은 프로젝트가 있어 예시 프로젝트를 하나 생성해보도록 하겠다.
1-1. 네이버 OAuth 서비스를 등록하기 위해 다음 링크를 통해 네이버 개발자 센터로 이동한다.
https://developers.naver.com/main/
NAVER Developers
네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음
developers.naver.com
1-2. 애플리케이션 등록 > 애플리케이션 이름 입력 > 사용 API 선택 (네이버 로그인) > 제공 정보 선택

1-3. 환경 추가 (PC 웹) > 서비스 URL 입력(http://localhost:8080) > 네이버 아이디로 로그인 입력(http://localhost:8080/login/oauth2/naver) > 등록하기

1-4. 클라이언트 아이디, 클라이언트 비밀번호 GET

2. application-oauth.properties
# GOOGLE ... # Naver spring.security.oauth2.client.registration.naver.client-id=클라이언트ID spring.security.oauth2.client.registration.naver.client-secret=클라이언트Secret # Naver Spring Security 수동 입력 # == http://localhost:8080/login/oauth2/code/naver spring.security.oauth2.client.registration.naver.redirect-uri={baseUrl}/{action}/oauth2/code/{registrationId} spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.naver.scope=name,email,nickname spring.security.oauth2.client.registration.naver.client-name=Naver # provider spring.security.oauth2.client.provider.naver.authorization-uri=https://nid.naver.com/oauth2.0/authorize spring.security.oauth2.client.provider.naver.token-uri=https://nid.naver.com/oauth2.0/token spring.security.oauth2.client.provider.naver.user-info-uri=https://openapi.naver.com/v1/nid/me # Security의 기준이 되는 username의 이름을 네이버에서는 response로 (회원 조회시 반환되는 JSON 형태 때문) spring.security.oauth2.client.provider.naver.user-name-attribute=response
네이버는 스프링 시큐리티를 공식 지원하지 않기 때문에 Provider를 직접 입력해줘야 한다.
자세한 가이드는 네이버 api 에 자세히 나와있으니 참고하자.
3. OAuthAttributes
@Slf4j @AllArgsConstructor @NoArgsConstructor @Builder @Getter public class OAuthAttributes { private Map<String, Object> attributes; private String nameAttributeKey; private String username; private String nickname; private String email; private Role role; public static OAuthAttributes of(String registrationId, String userNameAttributeName, Map<String, Object> attributes) { /* 구글인지 네이버인지 카카오인지 구분하기 위한 메소드 (ofNaver, ofKaKao) */ if ("naver".equals(registrationId)) { return ofNaver("id", attributes); } return ofGoogle(userNameAttributeName, attributes); } // ofGoogle 생략 private static OAuthAttributes ofNaver(String userNameAttributeName, Map<String, Object> attributes) { /* JSON형태이기 때문에 Map을 통해 데이터를 가져온다. */ Map<String, Object> response = (Map<String, Object>) attributes.get("response"); log.info("naver response : " + response); return OAuthAttributes.builder() .username((String) response.get("email")) .email((String) response.get("email")) .nickname((String) response.get("nickname")) .attributes(response) .nameAttributeKey(userNameAttributeName) .build(); } public User toEntity() { return User.builder() .username(email) .email(email) .nickname(nickname) .role(Role.SOCIAL) .build(); } }
OAuth2UserService를 통해 가져온 네이버 OAuth2User의 attributes를 담는다.
4. Mustache
header.mustache
<!DOCTYPE HTML> <html> <head> <title>Board Service</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.6.0/font/bootstrap-icons.css"> <link rel="stylesheet" href="/css/app.css"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> </head> <body> <div id="header"class="d-flex bd-highlight"> <a href="/" class="p-2 flex-grow-1 bd-highlight">Board Service</a> <form action="/posts/search" method="GET" class="form-inline p-2 bd-highlight" role="search"> <input type="text" name="keyword" class="form-control" id="search" placeholder="검색"> <button class="btn btn-success bi bi-search"></button> </form> </div> <nav id ="nav"> <div class="text-right"> {{#user}} <span class="mx-3">{{user}}님 안녕하세요!</span> <a href="/logout" class="btn btn-outline-dark">로그아웃</a> <a href="/modify" class="btn btn-outline-dark bi bi-gear"></a> {{/user}} {{^user}} <a href="/oauth2/authorization/naver" role="button" class="btn btn-outline-success"><img id="img" src="/img/naver.ico"/> 로그인</a> <a href="/oauth2/authorization/google" role="button" class="btn btn-outline-danger bi bi-google"> 로그인</a> <a href="/auth/login" role="button" class="btn btn-outline-dark bi bi-lock-fill"> 로그인</a> <a href="/auth/join" role="button" class="btn btn-outline-dark bi bi-person-circle"> 회원가입</a> {{/user}} </div> </nav>
로그인 url은 /oauth2/authorization/naver 으로 연결한다.
5. 결과 확인
5-1. 네이버 로그인 버튼 클릭
authorization_url로 이동한다.

5-2. 네이버 ID, PW 입력
아이디와 비밀번호가 일치하면 로그인 요청 코드가 담긴 콜백 url값을 보내고 그것을 oauth2.0/token이 전달받아 인증해준다.

5-3. 로그인 성공
인증이 성공하면 로그인이 완료된다.

블로그의 정보
슬기로운 개발생활
coco3o