JWT
1. 설정
- build.gradle에 dependency 추가하기
implementation 'com.auth0:java-jwt:4.4.0'
1) Dependency 추가
- build.gradle
- dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' }
- Maven Project
- <dependencies> <!-- ... other dependency elements ... --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies>
- application.properties
#JWT 설정
jwt.secretKey=F22rV7dQ4uHx2P6gv5lsJrE8mUcYn2023
# Access Token Configuration
#1시간(60분) (1000L(ms -> s) * 60L(s -> m) * 60L(m -> h))
jwt.access.expiration=3600000
jwt.access.header=Authorization
# Refresh Token Configuration
# (1000L(ms -> s) * 60L(s -> m) * 60L(m -> h) * 24L(h -> 하루) * 14(2주))
jwt.refresh.expiration=1209600000
jwt.refresh.header=Authorization-refresh
2. JwtService
- application.properties에서 설정한 값
@Value("${jwt.secretKey}")
private String secretKey;
@Value("${jwt.access.expiration}")
private Long accessTokenExpirationPeriod;
@Value("${jwt.refresh.expiration}")
private Long refreshTokenExpirationPeriod;
@Value("${jwt.access.header}")
private String accessHeader;
@Value("${jwt.refresh.header}")
private String refreshHeader;
SocialLogin
1. Resource Server에 Application 등록
카카오 또는 네이버에 애플리케이션 등록
2. application.properties 작성
# Google OAuth2
spring.security.oauth2.client.registration.google.client-id=구글 클라이언트 ID
spring.security.oauth2.client.registration.google.client-secret=구글 클라이언트 Secret
spring.security.oauth2.client.registration.google.scope=profile,email
# Naver OAuth2
spring.security.oauth2.client.registration.naver.client-id=네이버 클라이언트 ID
spring.security.oauth2.client.registration.naver.client-secret=네이버 클라이언트 Secret
spring.security.oauth2.client.registration.naver.redirect-uri=http://localhost:8080/login/oauth2/code/naver
spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.naver.scope=name,email,profile_image
spring.security.oauth2.client.registration.naver.client-name=Naver
# Kakao OAuth2
spring.security.oauth2.client.registration.kakao.client-id=카카오 클라이언트 ID
spring.security.oauth2.client.registration.kakao.client-secret=카카오 클라이언트 Secret
spring.security.oauth2.client.registration.kakao.redirect-uri=http://localhost:8080/login/oauth2/code/kakao
spring.security.oauth2.client.registration.kakao.client-authentication-method=POST
spring.security.oauth2.client.registration.kakao.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.kakao.scope=profile_nickname,profile_image
spring.security.oauth2.client.registration.kakao.client-name=Kakao
# Naver OAuth2 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
spring.security.oauth2.client.provider.naver.user-name-attribute=response
# Kakao OAuth2 Provider
spring.security.oauth2.client.provider.kakao.authorization-uri=https://kauth.kakao.com/oauth/authorize
spring.security.oauth2.client.provider.kakao.token-uri=https://kauth.kakao.com/oauth/token
spring.security.oauth2.client.provider.kakao.user-info-uri=https://kapi.kakao.com/v2/user/me
spring.security.oauth2.client.provider.kakao.user-name-attribute=id
- registration 부분
- OAuth 로그인 시 설정한 Application의 정보를 사용하여 AccessToken을 Authorization Server에게 발급받을 때 사용
- provider 부분
- AccessToken을 Authorization Server에게 발급 받은 후, 해당 AccessToken으로 Resource Server의 API를 사용할 때
- provider 부분의 정보를 사용하여 API 호출
3. 관련 클래스 생성
CustomOAuth2User
- OAuth2UserService에서 사용할 OAuth2User 객체 커스텀한 클래스
- 필요한 필드(닉네임) 추가하기 때문에 커스텀 필요
/**
* DefaultOAuth2User를 상속하고, nickname 필드를 추가로 가진다.
*/
@Getter
public class CustomOAuth2User extends DefaultOAuth2User {
private String nickname;
/**
* Constructs a {@code DefaultOAuth2User} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param attributes the attributes about the user
* @param nameAttributeKey the key used to access the user's "name" from
* {@link #getAttributes()}
*/
public CustomOAuth2User(Collection<? extends GrantedAuthority> authorities,
Map<String, Object> attributes, String nameAttributeKey,
String nickname) {
super(authorities, attributes, nameAttributeKey);
this.nickname= nickname;
}
}
Oauth DTO 클래스 - OAuthAttributes
- 소셜에서 받아오는 데이터가 다르므로 소셜별로 데이터를 받는 데이터를 분기 처리하는 DTO
- 이번 프로젝트는 카카오만 진행하므로 카카오 데이터 받는 부분만 구현하면 됨.
package login.oauthtest4.global.oauth2;
import login.oauthtest4.domain.user.Role;
import login.oauthtest4.domain.user.SocialType;
import login.oauthtest4.domain.user.User;
import login.oauthtest4.global.oauth2.userinfo.GoogleOAuth2UserInfo;
import login.oauthtest4.global.oauth2.userinfo.KakaoOAuth2UserInfo;
import login.oauthtest4.global.oauth2.userinfo.NaverOAuth2UserInfo;
import login.oauthtest4.global.oauth2.userinfo.OAuth2UserInfo;
import lombok.Builder;
import lombok.Getter;
import java.util.Map;
import java.util.UUID;
/**
* 각 소셜에서 받아오는 데이터가 다르므로
* 소셜별로 데이터를 받는 데이터를 분기 처리하는 DTO 클래스
*/
@Getter
public class OAuthAttributes {
private String nameAttributeKey; // OAuth2 로그인 진행 시 키가 되는 필드 값, PK와 같은 의미
private OAuth2UserInfo oauth2UserInfo; // 소셜 타입별 로그인 유저 정보(닉네임, 이메일, 프로필 사진 등등)
@Builder
public OAuthAttributes(String nameAttributeKey, OAuth2UserInfo oauth2UserInfo) {
this.nameAttributeKey = nameAttributeKey;
this.oauth2UserInfo = oauth2UserInfo;
}
/**
* SocialType에 맞는 메소드 호출하여 OAuthAttributes 객체 반환
* 파라미터 : userNameAttributeName -> OAuth2 로그인 시 키(PK)가 되는 값 / attributes : OAuth 서비스의 유저 정보들
* 소셜별 of 메소드(ofGoogle, ofKaKao, ofNaver)들은 각각 소셜 로그인 API에서 제공하는
* 회원의 식별값(id), attributes, nameAttributeKey를 저장 후 build
*/
private static OAuthAttributes ofKakao(String userNameAttributeName, Map<String, Object> attributes) {
return OAuthAttributes.builder()
.nameAttributeKey(userNameAttributeName)
.oauth2UserInfo(new KakaoOAuth2UserInfo(attributes))
.build();
}
/**
* of메소드로 OAuthAttributes 객체가 생성되어, 유저 정보들이 담긴 OAuth2UserInfo가 소셜 타입별로 주입된 상태
* OAuth2UserInfo에서 socialId(식별값), nickname, imageUrl을 가져와서 build
* email에는 UUID로 중복 없는 랜덤 값 생성
* role은 GUEST로 설정
*/
public User toEntity(SocialType socialType, OAuth2UserInfo oauth2UserInfo) {
return User.builder()
.socialType(socialType)
.socialId(oauth2UserInfo.getId())
.email(UUID.randomUUID() + "@socialUser.com")
.nickname(oauth2UserInfo.getNickname())
.imageUrl(oauth2UserInfo.getImageUrl())
.role(Role.GUEST)
.build();
}
}
'Learning-log > Spring & JPA' 카테고리의 다른 글
JPA vs Hibernate vs Spring JPA (2) | 2024.05.09 |
---|---|
[Spring Boot, 로그인] JWT란? JWT를 활용해서 Spring Boot에서 로그인 구현하기 ( JWT 회원정보 추출 커스텀 애노테이션 ) (0) | 2023.09.14 |
[Spring Boot] SpringSecurity 이해하기 (0) | 2023.09.02 |
(DB2편) 섹션5-3. JPA 소개 (0) | 2023.07.10 |
(스프링MVC1편-백엔드 웹 개발 핵심 기술) 3-(3)JSP로 회원관리 웹 애플리케이션 만들기, (4)MVC패턴 - 개요 (0) | 2023.05.11 |