-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 레디스 적용 및 로그아웃 api 추가 #40
Changes from all commits
d9647af
bd442bf
756096a
522fecd
252bc20
6595bc6
7d608b1
2c829ff
d364000
ed7f2f3
05423dc
f4389a2
fe68ceb
b0e0d5f
2ebf1ee
95cf36a
a4df6e8
fbeb794
3d29b7c
6ec0f14
407ea48
f463404
953e5a4
ce8714e
508194d
a3fb9f4
b80f3f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.atwoz.admin.application.auth; | ||
|
||
public interface AdminAccessTokenProvider { | ||
|
||
String createAccessToken(Long id); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.atwoz.admin.domain.admin; | ||
|
||
import com.atwoz.admin.domain.admin.service.AdminRefreshTokenProvider; | ||
import lombok.Builder; | ||
import org.springframework.data.annotation.Id; | ||
|
||
@Builder | ||
public record AdminRefreshToken( | ||
@Id String refreshToken, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 확인해보니 레디스로 관리할 경우에는 말씀하신 것 처럼 |
||
Long memberId | ||
) { | ||
|
||
public static AdminRefreshToken createWith(final AdminRefreshTokenProvider adminRefreshTokenProvider, | ||
final String email, | ||
final Long memberId) { | ||
return AdminRefreshToken.builder() | ||
.refreshToken(adminRefreshTokenProvider.createRefreshToken(email)) | ||
.memberId(memberId) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.atwoz.admin.domain.admin; | ||
|
||
import java.util.Optional; | ||
|
||
public interface AdminRefreshTokenRepository { | ||
|
||
void save(AdminRefreshToken adminRefreshToken); | ||
|
||
Optional<AdminRefreshToken> findById(String refreshToken); | ||
|
||
void delete(String refreshToken); | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.atwoz.admin.domain.admin.service; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AT 발급 인터페이스는 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저희가 RT만 레디스에 저장하기 때문에 RT 도메인 객체는 도메인에 위치해야합니다. 하지만 RT의 암호화된 토큰은 JwtTokenProvider에서 만들어집니다. 만약 JwtTokenProvider 통해 서비스 레이어에서 생성해준다면 RT 도메인 객체는 응용 계층에서 만든 암호화된 토큰을 받게 됩니다. 이로 인한 응용 계층의 의존이 생기기 때문에 RTProvider를 팩토리 메서드 인자로 넘겨줘서 내부에서 암호화된 토큰이 만들어지도록 구현해야한다고 생각했습니다. RTProvider는 도메인 서비스이기에 도메인 레이어에 위치해야합니다. 하지만 ATProvider는 도메인에 어떠한 영향도 미치지 않기 때문에 응용 계층에서 생성해서 응답 바디에 넘겨주면 됩니다. 제가 AT, RT 생성 기능을 모두 추상화한 인터페이스로 둔 이유가 바로 이 이유 때문이었습니다. 추가적인 의견 및 제가 잘못 이해해서 설계한 부분이 있다면 댓글로 의견 남겨주시면 감사하겠습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아 이해했습니다. AT 발급 (ATProvider)은 도메인에 영향을 미치지 않고 응용 계층에서만 이용되기 때문에 응용 계층에 인터페이스를 위치시키고, RT 발급 (RTPRovider)을 AT 발급처럼 응용 계층에 둔다면 도메인 계층에 있는 AdminRefreshToken에서 응용 계층에 대한 의존이 발생되기 때문에 도메인 패키지 하위에 서비스 패키지를 별도로 만들어주신거군요. |
||
|
||
public interface AdminRefreshTokenProvider { | ||
|
||
String createRefreshToken(String email); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.atwoz.admin.exception.exceptions; | ||
|
||
public class InvalidRefreshTokenException extends RuntimeException { | ||
|
||
public InvalidRefreshTokenException() { | ||
super("리프레쉬 토큰이 유효하지 않습니다"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.atwoz.admin.infrastructure.auth; | ||
|
||
import com.atwoz.admin.domain.admin.AdminRefreshToken; | ||
import com.atwoz.admin.domain.admin.AdminRefreshTokenRepository; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
import java.util.concurrent.TimeUnit; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.data.redis.core.ValueOperations; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@RequiredArgsConstructor | ||
@Repository | ||
public class AdminRedisRefreshTokenRepository implements AdminRefreshTokenRepository { | ||
|
||
@Value("${redis.expiration-period}") | ||
private int expirationPeriod; | ||
|
||
private final RedisTemplate<String, Long> redisTemplate; | ||
|
||
@Override | ||
public void save(final AdminRefreshToken adminRefreshToken) { | ||
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue(); | ||
valueOperations.set(adminRefreshToken.refreshToken(), adminRefreshToken.memberId()); | ||
redisTemplate.expire(adminRefreshToken.refreshToken(), expirationPeriod, TimeUnit.DAYS); | ||
} | ||
|
||
@Override | ||
public Optional<AdminRefreshToken> findById(final String refreshToken) { | ||
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue(); | ||
Long memberId = valueOperations.get(refreshToken); | ||
if (Objects.isNull(memberId)) { | ||
return Optional.empty(); | ||
} | ||
|
||
return Optional.of(new AdminRefreshToken(refreshToken, memberId)); | ||
} | ||
|
||
@Override | ||
public void delete(final String refreshToken) { | ||
redisTemplate.delete(refreshToken); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프론트엔드에서 헤더에서 토큰을 제거해주고 동시에 로그아웃 api를 요청해서 리프레쉬 토큰까지 제거해서 로그아웃을 시켜준다라는 의미로 작성하신 코드가 맞을까요?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 맞습니다!
프론트에서 로그아웃 처리시 로그아웃 api를 요청해서 서버에 있는 로그인 했던 유저의 RT를 삭제합니다!