Spring Boot 게시판 OAuth 2.0 네이버 로그인 구현
by coco3o이전 게시글에 이어서 네이버 OAuth 2.0 로그인을 구현하도록 하자.
1. 네이버 OAuth 서비스 등록
필자는 이미 만들어놓은 프로젝트가 있어 예시 프로젝트를 하나 생성해보도록 하겠다.
1-1. 네이버 OAuth 서비스를 등록하기 위해 다음 링크를 통해 네이버 개발자 센터로 이동한다.
https://developers.naver.com/main/
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. 로그인 성공
인증이 성공하면 로그인이 완료된다.
'📌ETC > Development Log' 카테고리의 다른 글
Spring Boot JPA 게시판 댓글 작성 및 조회 구현하기 (2) | 2022.01.04 |
---|---|
Spring Boot 게시판 JPA 연관관계 매핑으로 글 작성자만 수정, 삭제 가능하게 하기 (0) | 2021.12.30 |
Spring Boot 게시판 OAuth 2.0 구글 로그인 구현 (15) | 2021.12.28 |
Spring Boot 게시판 Security 회원정보 수정(ajax) 구현 (0) | 2021.12.22 |
Spring Boot 게시판 Security 로그인 실패시 메시지 출력하기 (2) | 2021.12.21 |
블로그의 정보
슬기로운 개발생활
coco3o