From 87e321e603f1b661f9e51a55bcb3847fcc2918c7 Mon Sep 17 00:00:00 2001 From: sunnyineverywhere Date: Mon, 11 Sep 2023 00:12:53 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[CHORE]=20=ED=8C=8C=EC=9D=BC=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- q-admin/src/main/java/com/qcard/config/WebConfig.java | 2 +- q-admin/src/main/java/com/qcard/jwt/JwtService.java | 4 +++- .../main/java/com/qcard/{auth => resolver}/AuthAccount.java | 2 +- .../{auth => resolver}/AuthAccountArgumentResolver.java | 2 +- .../com/qcard/{ => service}/CustomUserDetailService.java | 2 +- .../com/qcard/api/account/controller/AccountController.java | 2 +- .../com/qcard/api/answer/controller/AnswerController.java | 6 +----- .../com/qcard/api/heart/controller/HeartController.java | 2 +- .../qcard/api/question/controller/QuestionController.java | 5 +---- .../main/java/com/qcard/domains/account/entity/Account.java | 4 ---- 10 files changed, 11 insertions(+), 20 deletions(-) rename q-admin/src/main/java/com/qcard/{auth => resolver}/AuthAccount.java (91%) rename q-admin/src/main/java/com/qcard/{auth => resolver}/AuthAccountArgumentResolver.java (98%) rename q-admin/src/main/java/com/qcard/{ => service}/CustomUserDetailService.java (98%) diff --git a/q-admin/src/main/java/com/qcard/config/WebConfig.java b/q-admin/src/main/java/com/qcard/config/WebConfig.java index e1cd48a..7876b05 100644 --- a/q-admin/src/main/java/com/qcard/config/WebConfig.java +++ b/q-admin/src/main/java/com/qcard/config/WebConfig.java @@ -1,6 +1,6 @@ package com.qcard.config; -import com.qcard.auth.AuthAccountArgumentResolver; +import com.qcard.resolver.AuthAccountArgumentResolver; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/q-admin/src/main/java/com/qcard/jwt/JwtService.java b/q-admin/src/main/java/com/qcard/jwt/JwtService.java index 31f8e92..c02e7a8 100644 --- a/q-admin/src/main/java/com/qcard/jwt/JwtService.java +++ b/q-admin/src/main/java/com/qcard/jwt/JwtService.java @@ -1,5 +1,6 @@ package com.qcard.jwt; +import com.qcard.redis.RedisService; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -13,11 +14,12 @@ public class JwtService { private final JwtUtil jwtUtil; private final AuthenticationManagerBuilder authenticationManagerBuilder; private final PasswordEncoder passwordEncoder; + private final RedisService redisService; public TokenRes createJwt(String email, String password) { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(email, password); Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); - + redisService.setValues("a", "b"); return jwtUtil.generateToken(authentication); } diff --git a/q-admin/src/main/java/com/qcard/auth/AuthAccount.java b/q-admin/src/main/java/com/qcard/resolver/AuthAccount.java similarity index 91% rename from q-admin/src/main/java/com/qcard/auth/AuthAccount.java rename to q-admin/src/main/java/com/qcard/resolver/AuthAccount.java index 7372468..e9b9ce4 100644 --- a/q-admin/src/main/java/com/qcard/auth/AuthAccount.java +++ b/q-admin/src/main/java/com/qcard/resolver/AuthAccount.java @@ -1,4 +1,4 @@ -package com.qcard.auth; +package com.qcard.resolver; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/q-admin/src/main/java/com/qcard/auth/AuthAccountArgumentResolver.java b/q-admin/src/main/java/com/qcard/resolver/AuthAccountArgumentResolver.java similarity index 98% rename from q-admin/src/main/java/com/qcard/auth/AuthAccountArgumentResolver.java rename to q-admin/src/main/java/com/qcard/resolver/AuthAccountArgumentResolver.java index 62505d5..a4df260 100644 --- a/q-admin/src/main/java/com/qcard/auth/AuthAccountArgumentResolver.java +++ b/q-admin/src/main/java/com/qcard/resolver/AuthAccountArgumentResolver.java @@ -1,4 +1,4 @@ -package com.qcard.auth; +package com.qcard.resolver; import com.qcard.domains.account.service.AccountDomainService; import lombok.RequiredArgsConstructor; diff --git a/q-admin/src/main/java/com/qcard/CustomUserDetailService.java b/q-admin/src/main/java/com/qcard/service/CustomUserDetailService.java similarity index 98% rename from q-admin/src/main/java/com/qcard/CustomUserDetailService.java rename to q-admin/src/main/java/com/qcard/service/CustomUserDetailService.java index 2f9d793..660e49b 100644 --- a/q-admin/src/main/java/com/qcard/CustomUserDetailService.java +++ b/q-admin/src/main/java/com/qcard/service/CustomUserDetailService.java @@ -1,4 +1,4 @@ -package com.qcard; +package com.qcard.service; import com.qcard.domains.account.entity.Account; import com.qcard.domains.account.service.AccountDomainService; diff --git a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java index e6b8e81..3aadb03 100644 --- a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java +++ b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java @@ -7,7 +7,7 @@ import com.qcard.api.account.dto.AccountReq; import com.qcard.api.account.dto.AccountRes; import com.qcard.api.account.service.AccountService; -import com.qcard.auth.AuthAccount; +import com.qcard.resolver.AuthAccount; import com.qcard.jwt.TokenRes; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; diff --git a/q-api/src/main/java/com/qcard/api/answer/controller/AnswerController.java b/q-api/src/main/java/com/qcard/api/answer/controller/AnswerController.java index c4bb34a..a3b3479 100644 --- a/q-api/src/main/java/com/qcard/api/answer/controller/AnswerController.java +++ b/q-api/src/main/java/com/qcard/api/answer/controller/AnswerController.java @@ -3,14 +3,10 @@ import com.qcard.api.account.service.AccountService; import com.qcard.api.answer.dto.*; import com.qcard.api.answer.service.AnswerService; -import com.qcard.api.heart.dto.HeartReq; -import com.qcard.api.heart.dto.HeartRes; -import com.qcard.auth.AuthAccount; +import com.qcard.resolver.AuthAccount; import com.qcard.domains.account.entity.Account; -import com.qcard.domains.question.entity.Answer; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; diff --git a/q-api/src/main/java/com/qcard/api/heart/controller/HeartController.java b/q-api/src/main/java/com/qcard/api/heart/controller/HeartController.java index 9a47e10..119ff7a 100644 --- a/q-api/src/main/java/com/qcard/api/heart/controller/HeartController.java +++ b/q-api/src/main/java/com/qcard/api/heart/controller/HeartController.java @@ -2,7 +2,7 @@ import com.qcard.api.heart.dto.HeartRes; import com.qcard.api.heart.service.HeartService; -import com.qcard.auth.AuthAccount; +import com.qcard.resolver.AuthAccount; import com.qcard.domains.account.entity.Account; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; diff --git a/q-api/src/main/java/com/qcard/api/question/controller/QuestionController.java b/q-api/src/main/java/com/qcard/api/question/controller/QuestionController.java index 797acc5..37435ea 100644 --- a/q-api/src/main/java/com/qcard/api/question/controller/QuestionController.java +++ b/q-api/src/main/java/com/qcard/api/question/controller/QuestionController.java @@ -1,17 +1,14 @@ package com.qcard.api.question.controller; -import com.qcard.api.answer.dto.AnswerRes; import com.qcard.api.answer.service.AnswerService; import com.qcard.api.question.dto.QuestionDetailRes; import com.qcard.api.question.dto.QuestionMainRes; import com.qcard.api.question.dto.QuestionRes; import com.qcard.api.question.service.QuestionService; -import com.qcard.auth.AuthAccount; +import com.qcard.resolver.AuthAccount; import com.qcard.common.enums.Category; import com.qcard.domains.account.entity.Account; -import com.qcard.domains.question.entity.Answer; import lombok.RequiredArgsConstructor; -import org.apache.coyote.Response; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; diff --git a/q-domain/src/main/java/com/qcard/domains/account/entity/Account.java b/q-domain/src/main/java/com/qcard/domains/account/entity/Account.java index bc8df6a..bad81b9 100644 --- a/q-domain/src/main/java/com/qcard/domains/account/entity/Account.java +++ b/q-domain/src/main/java/com/qcard/domains/account/entity/Account.java @@ -24,15 +24,11 @@ public class Account { @Column private String password; - @Column - private Boolean isDeleted; - @Builder public Account(String name, String email, String password) { this.name = name; this.email = email; this.password = password; - this.isDeleted = Boolean.FALSE; } } From 2da8f33be2cc980adddf530efd18a4fb540abe58 Mon Sep 17 00:00:00 2001 From: sunnyineverywhere Date: Mon, 11 Sep 2023 00:13:10 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[FEAT]=20=EB=A0=88=EB=94=94=EC=8A=A4=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yaml | 15 ++++++++ gradlew | 0 q-admin/build.gradle | 2 ++ .../java/com/qcard/redis/RedisConfig.java | 34 +++++++++++++++++++ .../java/com/qcard/redis/RedisService.java | 34 +++++++++++++++++++ scripts/run-local.sh | 7 ++++ scripts/stop-local.sh | 4 +++ 7 files changed, 96 insertions(+) create mode 100644 docker-compose.yaml mode change 100644 => 100755 gradlew create mode 100644 q-admin/src/main/java/com/qcard/redis/RedisConfig.java create mode 100644 q-admin/src/main/java/com/qcard/redis/RedisService.java create mode 100644 scripts/run-local.sh create mode 100644 scripts/stop-local.sh diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..3e14fa5 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,15 @@ +version: '3' + +services: + redis: + image: redis:alpine + ports: + - 6379:6379 + qcard-server: + build: + context: . + dockerfile: ./Dockerfile + ports: + - 8080:8080 + depends_on: + - redis \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/q-admin/build.gradle b/q-admin/build.gradle index 9e0fcb4..66a7cfc 100644 --- a/q-admin/build.gradle +++ b/q-admin/build.gradle @@ -8,6 +8,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' diff --git a/q-admin/src/main/java/com/qcard/redis/RedisConfig.java b/q-admin/src/main/java/com/qcard/redis/RedisConfig.java new file mode 100644 index 0000000..0674545 --- /dev/null +++ b/q-admin/src/main/java/com/qcard/redis/RedisConfig.java @@ -0,0 +1,34 @@ +package com.qcard.redis; + +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.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Value("${spring.data.redis.host}") + private String host; + + @Value("${spring.data.redis.port}") + private int port; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(host, port); + } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 아래 두 라인을 작성하지 않으면, key값이 \xac\xed\x00\x05t\x00\x03sol 이렇게 조회된다. + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + return redisTemplate; + } +} diff --git a/q-admin/src/main/java/com/qcard/redis/RedisService.java b/q-admin/src/main/java/com/qcard/redis/RedisService.java new file mode 100644 index 0000000..e12d087 --- /dev/null +++ b/q-admin/src/main/java/com/qcard/redis/RedisService.java @@ -0,0 +1,34 @@ +package com.qcard.redis; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import java.time.Duration; + +@Service +@RequiredArgsConstructor +public class RedisService { + private final RedisTemplate redisTemplate; + + public void setValues(String key, String data) { + ValueOperations values = redisTemplate.opsForValue(); + values.set(key, data); + } + + public void setValues(String key, String data, Duration duration) { + ValueOperations values = redisTemplate.opsForValue(); + values.set(key, data, duration); + } + + public String getValues(String key) { + ValueOperations values = redisTemplate.opsForValue(); + return values.get(key); + } + + public void deleteValues(String key) { + redisTemplate.delete(key); + } +} diff --git a/scripts/run-local.sh b/scripts/run-local.sh new file mode 100644 index 0000000..ea8c5fa --- /dev/null +++ b/scripts/run-local.sh @@ -0,0 +1,7 @@ +REPOSITORY=../ +cd $REPOSITORY + +chmod +x gradlew +./gradlew clean build + +docker compose up \ No newline at end of file diff --git a/scripts/stop-local.sh b/scripts/stop-local.sh new file mode 100644 index 0000000..b7c7fd0 --- /dev/null +++ b/scripts/stop-local.sh @@ -0,0 +1,4 @@ +REPOSITORY=../ +cd $REPOSITORY + +docker compose down \ No newline at end of file From b06402f892c89a6c1e97414d7a968d355d72fb34 Mon Sep 17 00:00:00 2001 From: siyeonkm <68330823+siyeonkm@users.noreply.github.com> Date: Wed, 13 Sep 2023 00:38:49 +0900 Subject: [PATCH 3/8] =?UTF-8?q?[FEAT]=20redis=EC=97=90=20=EB=84=A3?= =?UTF-8?q?=EC=9D=84=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20entity=EC=99=80=20rep?= =?UTF-8?q?ository=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/qcard/redis/RedisTokenRepository.java | 6 ++++++ .../java/com/qcard/redis/RefreshToken.java | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java create mode 100644 q-admin/src/main/java/com/qcard/redis/RefreshToken.java diff --git a/q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java b/q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java new file mode 100644 index 0000000..9015a5d --- /dev/null +++ b/q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java @@ -0,0 +1,6 @@ +package com.qcard.redis; + +import org.springframework.data.repository.CrudRepository; + +public interface RedisTokenRepository extends CrudRepository { +} diff --git a/q-admin/src/main/java/com/qcard/redis/RefreshToken.java b/q-admin/src/main/java/com/qcard/redis/RefreshToken.java new file mode 100644 index 0000000..48f1831 --- /dev/null +++ b/q-admin/src/main/java/com/qcard/redis/RefreshToken.java @@ -0,0 +1,18 @@ +package com.qcard.redis; + +import jakarta.persistence.Id; +import lombok.Getter; +import org.springframework.data.redis.core.RedisHash; + +@Getter +@RedisHash(value = "refreshToken", timeToLive = 3600 * 24 * 14) +public class RefreshToken { + @Id + private String email; + private String refreshToken; + + public RefreshToken(String refreshToken, String email) { + this.refreshToken = refreshToken; + this.email = email; + } +} From 4b6d8c8b6d29a461a59eb51beccf13f1b0fdf73a Mon Sep 17 00:00:00 2001 From: siyeonkm <68330823+siyeonkm@users.noreply.github.com> Date: Thu, 14 Sep 2023 02:06:41 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[FEAT]=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/qcard/jwt/JwtFilter.java | 2 +- .../main/java/com/qcard/jwt/JwtService.java | 7 +++++-- .../src/main/java/com/qcard/jwt/JwtUtil.java | 1 + .../com/qcard/redis/RedisTokenRepository.java | 6 ------ .../java/com/qcard/redis/RefreshToken.java | 18 ------------------ .../account/controller/AccountController.java | 9 +++++++++ .../api/account/service/AccountService.java | 12 ++++++++++++ .../com/qcard/api/answer/dto/AnswerMeRes.java | 1 - 8 files changed, 28 insertions(+), 28 deletions(-) delete mode 100644 q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java delete mode 100644 q-admin/src/main/java/com/qcard/redis/RefreshToken.java diff --git a/q-admin/src/main/java/com/qcard/jwt/JwtFilter.java b/q-admin/src/main/java/com/qcard/jwt/JwtFilter.java index ce942f9..ef09501 100644 --- a/q-admin/src/main/java/com/qcard/jwt/JwtFilter.java +++ b/q-admin/src/main/java/com/qcard/jwt/JwtFilter.java @@ -13,6 +13,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; +import java.util.Objects; @RequiredArgsConstructor @Slf4j @@ -44,5 +45,4 @@ private String resolveToken(HttpServletRequest request) { return null; } - } diff --git a/q-admin/src/main/java/com/qcard/jwt/JwtService.java b/q-admin/src/main/java/com/qcard/jwt/JwtService.java index c02e7a8..a1df038 100644 --- a/q-admin/src/main/java/com/qcard/jwt/JwtService.java +++ b/q-admin/src/main/java/com/qcard/jwt/JwtService.java @@ -7,6 +7,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import java.time.Duration; @Service @RequiredArgsConstructor @@ -19,8 +20,10 @@ public class JwtService { public TokenRes createJwt(String email, String password) { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(email, password); Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); - redisService.setValues("a", "b"); - return jwtUtil.generateToken(authentication); + TokenRes tokenRes = jwtUtil.generateToken(authentication); + redisService.setValues(tokenRes.getRefreshToken(), email, Duration.ofDays(14)); + + return tokenRes; } public String encryptPassword(String password) { diff --git a/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java b/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java index dcffd82..1d282e1 100644 --- a/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java +++ b/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java @@ -84,6 +84,7 @@ public Long getExpiration(String accessToken) { return (expirationDate.getTime() - (new Date()).getTime()); } + public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); diff --git a/q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java b/q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java deleted file mode 100644 index 9015a5d..0000000 --- a/q-admin/src/main/java/com/qcard/redis/RedisTokenRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.qcard.redis; - -import org.springframework.data.repository.CrudRepository; - -public interface RedisTokenRepository extends CrudRepository { -} diff --git a/q-admin/src/main/java/com/qcard/redis/RefreshToken.java b/q-admin/src/main/java/com/qcard/redis/RefreshToken.java deleted file mode 100644 index 48f1831..0000000 --- a/q-admin/src/main/java/com/qcard/redis/RefreshToken.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.qcard.redis; - -import jakarta.persistence.Id; -import lombok.Getter; -import org.springframework.data.redis.core.RedisHash; - -@Getter -@RedisHash(value = "refreshToken", timeToLive = 3600 * 24 * 14) -public class RefreshToken { - @Id - private String email; - private String refreshToken; - - public RefreshToken(String refreshToken, String email) { - this.refreshToken = refreshToken; - this.email = email; - } -} diff --git a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java index 3aadb03..c204e94 100644 --- a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java +++ b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java @@ -9,6 +9,7 @@ import com.qcard.api.account.service.AccountService; import com.qcard.resolver.AuthAccount; import com.qcard.jwt.TokenRes; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -23,6 +24,7 @@ public class AccountController { private final AccountService accountService; private final AccountDomainService accountDomainService; + private static final String ACCESS_HEADER = "Authorization"; @PostMapping("/signup") public ResponseEntity signUp(@Valid @RequestBody AccountReq accountReq) { @@ -36,6 +38,13 @@ public ResponseEntity signIn(@Valid @RequestBody SignInReq signInReq) return new ResponseEntity<>(response, HttpStatus.OK); } + @PostMapping("/reissue") + public ResponseEntity accessTokenReissue(HttpServletRequest request) { + String bearerToken = request.getHeader(ACCESS_HEADER).substring(7); + accountService.reissueToken(bearerToken); + return new ResponseEntity<>(null, HttpStatus.OK); + } + @GetMapping("/profile") public ResponseEntity myAccountInfo(@AuthAccount Account account) { AccountRes response = new AccountRes(account.getName(), account.getEmail()); diff --git a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java index 77d609b..d481e9e 100644 --- a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java +++ b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java @@ -8,6 +8,8 @@ import com.qcard.api.account.dto.AccountRes; import com.qcard.jwt.JwtService; import com.qcard.jwt.TokenRes; +import com.qcard.redis.RedisService; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -17,6 +19,7 @@ public class AccountService { private final AccountDomainService accountDomainService; private final JwtService jwtService; + private final RedisService redisService; public SignUpRes signUp(AccountReq accountReq) { if (!accountReq.isValid()) { @@ -43,4 +46,13 @@ public TokenRes signIn(SignInReq signInReq) { throw new IllegalArgumentException("비밀번호가 올바르지 않습니다."); } } + + public TokenRes reissueToken(String bearerToken) { + String email = redisService.getValues(bearerToken); + if(email != null) { + Account account = accountDomainService.findAccountByEmail(email); + // TODO: access만 발급하는 함수 필요 + jwtService.createJwt(account.getEmail(), account.getPassword()); + } + } } diff --git a/q-api/src/main/java/com/qcard/api/answer/dto/AnswerMeRes.java b/q-api/src/main/java/com/qcard/api/answer/dto/AnswerMeRes.java index 5c60b56..c1b9563 100644 --- a/q-api/src/main/java/com/qcard/api/answer/dto/AnswerMeRes.java +++ b/q-api/src/main/java/com/qcard/api/answer/dto/AnswerMeRes.java @@ -15,7 +15,6 @@ @NoArgsConstructor public class AnswerMeRes { private Question question; - private Long answerId; private Type type; private AccountRes account; From 096b303a3095be733cd4f95255cc26bc37f1c092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A7=88=EC=BD=94=EB=A0=88?= Date: Sat, 16 Sep 2023 03:33:05 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[FEAT]=EC=9E=AC=EB=B0=9C=EA=B8=89=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/qcard/jwt/JwtService.java | 7 +++++++ .../src/main/java/com/qcard/jwt/JwtUtil.java | 19 +++++++++++++++++++ .../account/controller/AccountController.java | 13 ++++++++++--- .../api/account/service/AccountService.java | 19 +++++++++++++++---- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/q-admin/src/main/java/com/qcard/jwt/JwtService.java b/q-admin/src/main/java/com/qcard/jwt/JwtService.java index a1df038..55a976d 100644 --- a/q-admin/src/main/java/com/qcard/jwt/JwtService.java +++ b/q-admin/src/main/java/com/qcard/jwt/JwtService.java @@ -26,6 +26,13 @@ public TokenRes createJwt(String email, String password) { return tokenRes; } + public TokenRes reissueJwt(String email, String password, String refreshToken) { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(email, password); + Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); + + return jwtUtil.reissueToken(authentication, refreshToken); + } + public String encryptPassword(String password) { return passwordEncoder.encode(password); } diff --git a/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java b/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java index 1d282e1..12b896b 100644 --- a/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java +++ b/q-admin/src/main/java/com/qcard/jwt/JwtUtil.java @@ -53,6 +53,25 @@ public TokenRes generateToken(Authentication authentication) { .build(); } + public TokenRes reissueToken(Authentication authentication, String refreshToken) { + Long current = (new Date()).getTime(); + + String authorities = authentication.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.joining(",")); + + String accessToken = Jwts.builder() + .setSubject(authentication.getName()) + .claim(AUTHORITIES_KEY, authorities) + .setExpiration(new Date(current + ACCESS_TOKEN_EXPIRE_TIME)) + .signWith(key, SignatureAlgorithm.HS256).compact(); + + return TokenRes.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); + } + public Authentication getAuthentication(String accessToken) { Claims claims = parseClaims(accessToken); diff --git a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java index c204e94..30f900b 100644 --- a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java +++ b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java @@ -38,11 +38,18 @@ public ResponseEntity signIn(@Valid @RequestBody SignInReq signInReq) return new ResponseEntity<>(response, HttpStatus.OK); } - @PostMapping("/reissue") + @GetMapping("/reissue") public ResponseEntity accessTokenReissue(HttpServletRequest request) { String bearerToken = request.getHeader(ACCESS_HEADER).substring(7); - accountService.reissueToken(bearerToken); - return new ResponseEntity<>(null, HttpStatus.OK); + TokenRes response = accountService.reissueToken(bearerToken); + return new ResponseEntity<>(response, HttpStatus.OK); + } + + @GetMapping("/logout") + public ResponseEntity logOut(HttpServletRequest request) { + String refreshToken = request.getHeader(ACCESS_HEADER).substring(7); + accountService.logout(refreshToken); + return new ResponseEntity<>("로그아웃 성공", HttpStatus.OK); } @GetMapping("/profile") diff --git a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java index d481e9e..e2d5222 100644 --- a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java +++ b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java @@ -47,12 +47,23 @@ public TokenRes signIn(SignInReq signInReq) { } } - public TokenRes reissueToken(String bearerToken) { - String email = redisService.getValues(bearerToken); + public TokenRes reissueToken(String refreshToken) { + String email = redisService.getValues(refreshToken); if(email != null) { Account account = accountDomainService.findAccountByEmail(email); - // TODO: access만 발급하는 함수 필요 - jwtService.createJwt(account.getEmail(), account.getPassword()); + return jwtService.reissueJwt(account.getEmail(), account.getPassword(), refreshToken); + } + else { + throw new IllegalArgumentException("회원가입을 한 적 없는 유저입니다."); + } + } + + public void logout(String refreshToken) { + try{ + redisService.deleteValues(refreshToken); + } + catch(Exception e){ + throw new RuntimeException("로그아웃에 실패했습니다."); } } } From 4c398b52152a897413ecfe2090ba37280d784daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A7=88=EC=BD=94=EB=A0=88?= Date: Sat, 16 Sep 2023 21:38:58 +0900 Subject: [PATCH 6/8] =?UTF-8?q?[FIX]=20refreshToken=20substring=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/qcard/api/account/controller/AccountController.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java index 30f900b..cec7072 100644 --- a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java +++ b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java @@ -40,15 +40,13 @@ public ResponseEntity signIn(@Valid @RequestBody SignInReq signInReq) @GetMapping("/reissue") public ResponseEntity accessTokenReissue(HttpServletRequest request) { - String bearerToken = request.getHeader(ACCESS_HEADER).substring(7); - TokenRes response = accountService.reissueToken(bearerToken); + TokenRes response = accountService.reissueToken(request.getHeader(ACCESS_HEADER)); return new ResponseEntity<>(response, HttpStatus.OK); } @GetMapping("/logout") public ResponseEntity logOut(HttpServletRequest request) { - String refreshToken = request.getHeader(ACCESS_HEADER).substring(7); - accountService.logout(refreshToken); + accountService.logout(request.getHeader(ACCESS_HEADER)); return new ResponseEntity<>("로그아웃 성공", HttpStatus.OK); } From 06c5059b82c2ead6ba24e6e1b5adc2f62a37addd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A7=88=EC=BD=94=EB=A0=88?= Date: Sun, 17 Sep 2023 02:21:52 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[FEAT]=20refreshtoken=20=EC=97=86=EC=9D=B4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=20=EC=8B=9C=EB=8F=84?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yaml | 1 + .../account/controller/AccountController.java | 11 ++++------- .../com/qcard/api/account/dto/LogOutRes.java | 16 ++++++++++++++++ .../api/account/service/AccountService.java | 17 +++++++++-------- 4 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 q-api/src/main/java/com/qcard/api/account/dto/LogOutRes.java diff --git a/docker-compose.yaml b/docker-compose.yaml index 3e14fa5..8353b6d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,6 +6,7 @@ services: ports: - 6379:6379 qcard-server: + platform: linux/amd64 build: context: . dockerfile: ./Dockerfile diff --git a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java index cec7072..702ae2e 100644 --- a/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java +++ b/q-api/src/main/java/com/qcard/api/account/controller/AccountController.java @@ -1,11 +1,8 @@ package com.qcard.api.account.controller; -import com.qcard.api.account.dto.SignInReq; -import com.qcard.api.account.dto.SignUpRes; +import com.qcard.api.account.dto.*; import com.qcard.domains.account.entity.Account; import com.qcard.domains.account.service.AccountDomainService; -import com.qcard.api.account.dto.AccountReq; -import com.qcard.api.account.dto.AccountRes; import com.qcard.api.account.service.AccountService; import com.qcard.resolver.AuthAccount; import com.qcard.jwt.TokenRes; @@ -45,9 +42,9 @@ public ResponseEntity accessTokenReissue(HttpServletRequest request) { } @GetMapping("/logout") - public ResponseEntity logOut(HttpServletRequest request) { - accountService.logout(request.getHeader(ACCESS_HEADER)); - return new ResponseEntity<>("로그아웃 성공", HttpStatus.OK); + public ResponseEntity logOut(HttpServletRequest request) { + LogOutRes response = accountService.logout(request.getHeader(ACCESS_HEADER)); + return new ResponseEntity<>(response, HttpStatus.OK); } @GetMapping("/profile") diff --git a/q-api/src/main/java/com/qcard/api/account/dto/LogOutRes.java b/q-api/src/main/java/com/qcard/api/account/dto/LogOutRes.java new file mode 100644 index 0000000..f1eb527 --- /dev/null +++ b/q-api/src/main/java/com/qcard/api/account/dto/LogOutRes.java @@ -0,0 +1,16 @@ +package com.qcard.api.account.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class LogOutRes { + private String email; + private String message; + + public LogOutRes(String email) { + this.email = email; + this.message = "성공적으로 로그아웃했습니다."; + } +} diff --git a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java index e2d5222..496dd42 100644 --- a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java +++ b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java @@ -1,11 +1,8 @@ package com.qcard.api.account.service; -import com.qcard.api.account.dto.SignInReq; -import com.qcard.api.account.dto.SignUpRes; +import com.qcard.api.account.dto.*; import com.qcard.domains.account.entity.Account; import com.qcard.domains.account.service.AccountDomainService; -import com.qcard.api.account.dto.AccountReq; -import com.qcard.api.account.dto.AccountRes; import com.qcard.jwt.JwtService; import com.qcard.jwt.TokenRes; import com.qcard.redis.RedisService; @@ -15,6 +12,7 @@ import org.springframework.stereotype.Service; @Service +@Slf4j @RequiredArgsConstructor public class AccountService { private final AccountDomainService accountDomainService; @@ -58,12 +56,15 @@ public TokenRes reissueToken(String refreshToken) { } } - public void logout(String refreshToken) { - try{ + public LogOutRes logout(String refreshToken) { + String email = redisService.getValues(refreshToken); + log.info("email: " + email); + if(email != null){ redisService.deleteValues(refreshToken); + return new LogOutRes(email); } - catch(Exception e){ - throw new RuntimeException("로그아웃에 실패했습니다."); + else{ + throw new IllegalArgumentException("refresh token이 없습니다."); } } } From b4923413fa69d909eb0ac095e570b32b43a3389d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A7=88=EC=BD=94=EB=A0=88?= Date: Sun, 17 Sep 2023 02:24:37 +0900 Subject: [PATCH 8/8] =?UTF-8?q?[CHORE]=20=EC=97=90=EB=9F=AC=EB=A9=94?= =?UTF-8?q?=EC=84=B8=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/qcard/api/account/service/AccountService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java index 496dd42..beefa2a 100644 --- a/q-api/src/main/java/com/qcard/api/account/service/AccountService.java +++ b/q-api/src/main/java/com/qcard/api/account/service/AccountService.java @@ -52,7 +52,7 @@ public TokenRes reissueToken(String refreshToken) { return jwtService.reissueJwt(account.getEmail(), account.getPassword(), refreshToken); } else { - throw new IllegalArgumentException("회원가입을 한 적 없는 유저입니다."); + throw new IllegalArgumentException("잘못된 refresh token입니다."); } } @@ -64,7 +64,7 @@ public LogOutRes logout(String refreshToken) { return new LogOutRes(email); } else{ - throw new IllegalArgumentException("refresh token이 없습니다."); + throw new IllegalArgumentException("잘못된 refresh token입니다."); } } }