From 9221ff6624ae19969addd7b521b3bee28bbcd867 Mon Sep 17 00:00:00 2001 From: aeeazip Date: Thu, 6 Jul 2023 00:07:55 +0900 Subject: [PATCH] =?UTF-8?q?fix(#5)=20:=20DB=20refreshToken=20=EC=B9=BC?= =?UTF-8?q?=EB=9F=BC=20=EC=82=AD=EC=A0=9C,=20redis=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++ .../trothly/trothcam/config/RedisConfig.java | 41 +++++++++++++++++++ .../trothcam/domain/member/Member.java | 14 ------- .../trothly/trothcam/service/JwtService.java | 8 ++-- .../trothcam/service/auth/OAuthService.java | 30 ++++++++++---- src/main/resources/application-local.yml | 6 +-- 6 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 src/main/java/trothly/trothcam/config/RedisConfig.java diff --git a/build.gradle b/build.gradle index 7db433b..82969ad 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,9 @@ dependencies { implementation 'org.jsoup:jsoup:1.14.2' implementation 'com.google.code.gson:gson:2.8.7' + // Redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' diff --git a/src/main/java/trothly/trothcam/config/RedisConfig.java b/src/main/java/trothly/trothcam/config/RedisConfig.java new file mode 100644 index 0000000..3b556e4 --- /dev/null +++ b/src/main/java/trothly/trothcam/config/RedisConfig.java @@ -0,0 +1,41 @@ +package trothly.trothcam.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableRedisRepositories +public class RedisConfig { + + @Value("${spring.redis.host}") + private String redisHost; + + @Value("${spring.redis.port}") + private int redisPort; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(redisHost, redisPort); + } + + @Bean + public RedisTemplate redisTemplate() { + // redisTemplate를 받아와서 set, get, delete를 사용 + RedisTemplate redisTemplate = new RedisTemplate<>(); + /** + * setKeySerializer, setValueSerializer 설정 + * redis-cli을 통해 직접 데이터를 조회 시 알아볼 수 없는 형태로 출력되는 것을 방지 + */ + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + + return redisTemplate; + } +} diff --git a/src/main/java/trothly/trothcam/domain/member/Member.java b/src/main/java/trothly/trothcam/domain/member/Member.java index 2e50d57..9e81008 100644 --- a/src/main/java/trothly/trothcam/domain/member/Member.java +++ b/src/main/java/trothly/trothcam/domain/member/Member.java @@ -8,7 +8,6 @@ import javax.persistence.*; import javax.validation.constraints.Email; -import java.time.LocalDateTime; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -34,22 +33,9 @@ public class Member extends BaseTimeEntity { @Enumerated(EnumType.STRING) private Provider provider; - @Column(name = "refresh_token", nullable = false) - private String refreshToken; - - @Column(name = "refresh_token_expires_at", nullable = false) - private LocalDateTime refreshTokenExpiresAt; - @Builder private Member(String email, Provider provider) { this.email = email; this.provider = provider; - this.refreshToken = ""; - this.refreshTokenExpiresAt = LocalDateTime.now(); - } - - public void updateRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - this.refreshTokenExpiresAt = LocalDateTime.now(); } } diff --git a/src/main/java/trothly/trothcam/service/JwtService.java b/src/main/java/trothly/trothcam/service/JwtService.java index 0fdd628..91179a8 100644 --- a/src/main/java/trothly/trothcam/service/JwtService.java +++ b/src/main/java/trothly/trothcam/service/JwtService.java @@ -3,6 +3,7 @@ import io.jsonwebtoken.*; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; @@ -23,6 +24,7 @@ public class JwtService { @Value("${jwt.secret}") private String JWT_SECRET; + private final RedisTemplate redisTemplate; private final MemberRepository memberRepository; public String encodeJwtToken(TokenDto tokenDto) { @@ -103,11 +105,9 @@ public Boolean validateRefreshToken(String token) { // 유저 리프레쉬 토큰 확인 Long memberId = getMemberIdFromJwtToken(token); + String redisRefreshToken = redisTemplate.opsForValue().get(memberId.toString()); - Member member = memberRepository.findById(memberId) - .orElseThrow(()-> new IllegalArgumentException("해당되는 사용자를 찾을 수 없습니다.")); - - if(member.getRefreshToken().equals(token)){ + if(redisRefreshToken.equals(token)){ return true; } return false; diff --git a/src/main/java/trothly/trothcam/service/auth/OAuthService.java b/src/main/java/trothly/trothcam/service/auth/OAuthService.java index 4677b1b..24cadc6 100644 --- a/src/main/java/trothly/trothcam/service/auth/OAuthService.java +++ b/src/main/java/trothly/trothcam/service/auth/OAuthService.java @@ -3,6 +3,8 @@ import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import trothly.trothcam.dto.auth.TokenDto; import trothly.trothcam.dto.auth.apple.LoginReqDto; @@ -16,6 +18,7 @@ import trothly.trothcam.service.JwtService; import java.util.Optional; +import java.util.concurrent.TimeUnit; @Service @RequiredArgsConstructor @@ -24,6 +27,7 @@ public class OAuthService { private final AppleOAuthUserProvider appleOAuthUserProvider; private final MemberRepository memberRepository; + private final RedisTemplate redisTemplate; private final JwtService jwtService; @@ -59,28 +63,36 @@ public LoginResDto appleLogin(LoginReqDto loginReqDto) throws BaseException { logger.info("accessToken : " + newAccessToken); logger.info("refreshToken : " + newRefreshToken); - member.updateRefreshToken(newRefreshToken); - memberRepository.save(member); + // redis에 refreshToken 저장 + try { + redisTemplate.opsForValue().set(newRefreshToken, member.getId().toString(), 14L, TimeUnit.SECONDS); + } catch(Exception e) { + e.printStackTrace(); + } + // Redis에 저장 (key: userId, value: refreshToken) return new LoginResDto(newAccessToken, newRefreshToken); } // refreshToken으로 accessToken 발급하기 public LoginResDto regenerateAccessToken(RefreshTokenReqDto refreshTokenReqDto) throws BaseException { Long memberId = refreshTokenReqDto.getMemberId(); - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new IllegalArgumentException("해당되는 member_id를 찾을 수 없습니다.")); - String refreshToken = refreshTokenReqDto.getRefreshToken(); - if(refreshToken.equals(member.getRefreshToken())) + String getRefreshToken = refreshTokenReqDto.getRefreshToken(); + String redisRefreshToken = redisTemplate.opsForValue().get(memberId.toString()); + + if(getRefreshToken.equals(redisRefreshToken)) throw new InvalidTokenException("유효하지 않은 Refresh Token입니다."); String newRefreshToken = jwtService.encodeJwtRefreshToken(memberId); String newAcessToken = jwtService.encodeJwtToken(new TokenDto(memberId)); - member.updateRefreshToken(newRefreshToken); - memberRepository.save(member); - + try { + redisTemplate.opsForValue().set(newRefreshToken, memberId.toString(), 14L, TimeUnit.SECONDS); + logger.info("성공"); + } catch(Exception e) { + e.printStackTrace(); + } return new LoginResDto(newAcessToken, newRefreshToken); } } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 3517748..d9fd684 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -16,9 +16,9 @@ spring: default_batch_fetch_size: 1000 show-sql: true - # redis: -# host: localhost -# port: 6379 + redis: + host: localhost + port: 6379 config: activate: