From 33fd2a82e36b225d1e5f59783b2e973fa73d4283 Mon Sep 17 00:00:00 2001 From: Park Seyeon Date: Wed, 29 Nov 2023 15:28:01 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Base64=EA=B4=80=EB=A0=A8=20=EB=94=94?= =?UTF-8?q?=EC=BD=94=EB=94=A9=20=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?->=20Base64Url=20(#173)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Base64관련 디코딩 코드 변경 -> Base64Url * refactor: 쿠폰 스케쥴 업데이트 및 config 수정 * style: 문자열 checkstyle 수정 --- .../auth/JwtAuthenticationService.java | 8 +- src/main/resources/config | 2 +- src/main/resources/static/docs/coupon.html | 2869 +++++++++++++---- src/main/resources/static/docs/index.html | 2 +- .../resources/static/docs/notification.html | 2 +- .../auth/JwtProviderServiceTest.java | 37 +- 6 files changed, 2314 insertions(+), 606 deletions(-) diff --git a/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java b/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java index f43c4aa3..eaf1d456 100644 --- a/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java +++ b/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java @@ -1,6 +1,6 @@ package com.moabam.api.application.auth; -import java.util.Base64; +import java.nio.charset.StandardCharsets; import org.json.JSONObject; import org.springframework.stereotype.Service; @@ -13,6 +13,7 @@ import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.io.Decoders; import lombok.RequiredArgsConstructor; @Service @@ -37,8 +38,9 @@ public boolean isTokenExpire(String token) { public PublicClaim parseClaim(String token) { String claims = token.split("\\.")[1]; - String decodeClaims = new String(Base64.getDecoder().decode(claims)); - JSONObject jsonObject = new JSONObject(decodeClaims); + byte[] claimsBytes = Decoders.BASE64URL.decode(claims); + String decodedClaims = new String(claimsBytes, StandardCharsets.UTF_8); + JSONObject jsonObject = new JSONObject(decodedClaims); return AuthorizationMapper.toPublicClaim(jsonObject); } diff --git a/src/main/resources/config b/src/main/resources/config index 0f4c27e5..6320f486 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit 0f4c27e5bb593650ad4733c98f5c27b54eebc3c2 +Subproject commit 6320f4860f0be17c32492602f152b6d5a2f9f508 diff --git a/src/main/resources/static/docs/coupon.html b/src/main/resources/static/docs/coupon.html index 0b834827..d2b00d0d 100644 --- a/src/main/resources/static/docs/coupon.html +++ b/src/main/resources/static/docs/coupon.html @@ -1,467 +1,2138 @@ - - - - -쿠폰(Coupon) - - + + + + + 쿠폰(Coupon) + +
-
-

쿠폰(Coupon)

-
-
-
-
쿠폰에 대해 생성/삭제/조회/발급/사용 기능을 제공합니다.
-
-
-
-
-

쿠폰 생성

-
-
-
관리자가 쿠폰을 생성합니다.
-
-
-

요청

-
-
+
+

쿠폰(Coupon)

+
+
+
+
쿠폰에 대해 생성/삭제/조회/발급/사용 기능을 제공합니다.
+
+
+
+
+

쿠폰 생성

+
+
+
관리자가 쿠폰을 생성합니다.
+
+
+

요청

+
+
POST /admins/coupons HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Content-Length: 175
+Content-Length: 183
 Host: localhost:8080
 
 {
@@ -473,66 +2144,66 @@ 

요청

"startAt" : "2023-02-01", "openAt" : "2023-01-01" }
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 201 Created
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
 Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
 Access-Control-Allow-Credentials: true
 Access-Control-Max-Age: 3600
-
-
-
-
-
-

쿠폰 삭제

-
-
-
관리자가 쿠폰 ID와 일치하는 쿠폰을 삭제합니다.
-
-
-

요청

-
-
+
+
+
+
+
+

쿠폰 삭제

+
+
+
관리자가 쿠폰 ID와 일치하는 쿠폰을 삭제합니다.
+
+
+

요청

+
+
DELETE /admins/coupons/34 HTTP/1.1
 Host: localhost:8080
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
 Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
 Access-Control-Allow-Credentials: true
 Access-Control-Max-Age: 3600
-
-
-
-
-
-

특정 쿠폰 조회

-
-
-
관리자 혹은 사용자가 특정 ID와 일치하는 쿠폰을 조회합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+

특정 쿠폰 조회

+
+
+
관리자 혹은 사용자가 특정 ID와 일치하는 쿠폰을 조회합니다.
+
+
+
+

요청

+
+
GET /coupons/22 HTTP/1.1
 Host: localhost:8080
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -540,7 +2211,7 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 198 +Content-Length: 208 { "id" : 22, @@ -553,36 +2224,36 @@

응답

"startAt" : "2023-02-01", "openAt" : "2023-01-01" }
-
-
-
-
-
-
-

상태에 따른 쿠폰들을 조회

-
-
-
관리자 혹은 사용자가 날짜 상태에 따라 쿠폰들을 조회합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

상태에 따른 쿠폰들을 조회

+
+
+
관리자 혹은 사용자가 날짜 상태에 따라 쿠폰들을 조회합니다.
+
+
+
+

요청

+
+
POST /coupons/search HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Content-Length: 41
+Content-Length: 44
 Host: localhost:8080
 
 {
   "opened" : false,
   "ended" : false
 }
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -590,7 +2261,7 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 199 +Content-Length: 209 [ { "id" : 23, @@ -603,33 +2274,33 @@

응답

"startAt" : "2023-03-01", "openAt" : "2023-01-01" } ]
-
-
-
-
-
-
-

특정 쿠폰에 대해 발급

-
-
-
사용자가 발급 가능한 쿠폰을 선착순으로 발급 받습니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

특정 쿠폰에 대해 발급

+
+
+
사용자가 발급 가능한 쿠폰을 선착순으로 발급 받습니다.
+
+
+
+

요청

+
+
POST /coupons HTTP/1.1
 Content-Type: application/x-www-form-urlencoded
 Host: localhost:8080
 Content-Length: 21
 
 couponName=couponName
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 400 Bad Request
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -637,34 +2308,34 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 64 +Content-Length: 66 { "message" : "쿠폰 발급 가능 기간이 아닙니다." }
-
-
-
-
-
-
-

특정 사용자의 쿠폰 보관함을 조회

-
-
-
사용자가 자신의 보관함에 있는 쿠폰들을 조회합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

특정 사용자의 쿠폰 보관함을 조회

+
+
+
사용자가 자신의 보관함에 있는 쿠폰들을 조회합니다.
+
+
+
+

요청

+
+
GET /my-coupons HTTP/1.1
 Host: localhost:8080
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -672,7 +2343,7 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 472 +Content-Length: 502 [ { "id" : 17, @@ -705,49 +2376,49 @@

응답

"point" : 10, "type" : "MORNING" } ]
-
-
-
-
-
-
-

쿠폰을 사용

-
-
-
사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

쿠폰을 사용

+
+
+
사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다.
+
+
+
+

요청

+
+
POST /my-coupons/8 HTTP/1.1
 Host: localhost:8080
 Content-Type: application/x-www-form-urlencoded
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
 Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
 Access-Control-Allow-Credentials: true
 Access-Control-Max-Age: 3600
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- \ No newline at end of file + diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html index 62f80fd6..2f33f008 100644 --- a/src/main/resources/static/docs/index.html +++ b/src/main/resources/static/docs/index.html @@ -616,7 +616,7 @@

diff --git a/src/main/resources/static/docs/notification.html b/src/main/resources/static/docs/notification.html index d56f528e..6f789844 100644 --- a/src/main/resources/static/docs/notification.html +++ b/src/main/resources/static/docs/notification.html @@ -513,7 +513,7 @@

응답

diff --git a/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java b/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java index e9190c28..9c985f57 100644 --- a/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java +++ b/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java @@ -9,14 +9,16 @@ import org.json.JSONObject; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import com.moabam.api.application.auth.JwtProviderService; import com.moabam.global.auth.model.PublicClaim; import com.moabam.global.config.TokenConfig; import com.moabam.support.fixture.PublicClaimFixture; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.io.Decoders; class JwtProviderServiceTest { @@ -56,6 +58,39 @@ void create_access_token_success() throws JSONException { assertThat(iat).isLessThan(exp); } + @DisplayName("토큰 디코딩 실패") + @Test + void decoding_token_failBy_url() { + // given + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + + ".eyJpc3MiOiJtb2Ftb2Ftb2FiYW0iLCJpYXQiOjE3MDEyMzQyNjksImV4c" + + "CI6MTcwMTIzNDU2OSwiaWQiOjIsIm5pY2tuYW1lIjoiXHVEODNEXHVEQzNC6rOw64-M7J20Iiwicm9sZSI6IlVTRVIifQ" + + ".yVcvshWQ6fsQ0OQ-A5kolDo-8QsLVFCD6dIENKWZH-A"; + String[] parts = token.split("\\."); + + // when + then + assertThatThrownBy(() -> Base64.getDecoder().decode(parts[1])).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("토큰 디코딩 성공") + @ParameterizedTest + @ValueSource(strings = { + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + + ".eyJpc3MiOiJtb2Ftb2Ftb2FiYW0iLCJpYXQiOjE3MDEyMzQyNjksImV4cCI6MTcwMjQ0Mzg2OX0" + + ".IrcH_LvBKK1HezgY3PVY-0HQlhP6neEuydH6Mhz4Jgo", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + + ".eyJpc3MiOiJtb2Ftb2Ftb2FiYW0iLCJpYXQiOjE3MDEyMzQyNjksImV4cCI6MTcwMTIzNDU2OSwiaWQiOjIsIm" + + "5pY2tuYW1lIjoiXHVEODNEXHVEQzNC6rOw64-M7J20Iiwicm9sZSI6IlVTRVIifQ" + + ".yVcvshWQ6fsQ0OQ-A5kolDo-8QsLVFCD6dIENKWZH-A" + }) + void decoding_token_success(String token) { + // given + String[] parts = token.split("\\."); + + // When + Then + assertThatNoException().isThrownBy(() -> Decoders.BASE64URL.decode(parts[1])); + } + @DisplayName("refresh 토큰 생성 성공") @Test void create_refresh_token_success() throws JSONException {