From 881a3b065c18d3ec050953622054b3a88031ddd9 Mon Sep 17 00:00:00 2001 From: leebs0521 Date: Sat, 30 Nov 2024 17:44:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat(jwt):=20JwtAuthFilter=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20=20-=20Au?= =?UTF-8?q?thorization=20=EC=97=86=EB=8B=A4=EB=A9=B4=20=EC=9D=B5=EB=AA=85?= =?UTF-8?q?=20=EC=9C=A0=EC=A0=80=20=20-=20Authorization=20=EC=9E=88?= =?UTF-8?q?=EB=8B=A4=EB=A9=B4=20Bearer=20=EC=9D=B8=EC=A6=9D=20=EC=9E=91?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/somemore/auth/jwt/filter/JwtAuthFilter.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java b/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java index 08ced03a6..0fce0bbe3 100644 --- a/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java +++ b/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.List; +import software.amazon.awssdk.services.s3.endpoints.internal.Value.Str; @RequiredArgsConstructor @Slf4j @@ -29,8 +30,8 @@ public class JwtAuthFilter extends OncePerRequestFilter { @Override protected boolean shouldNotFilter(HttpServletRequest request) { - return true; // 개발 중 모든 요청 허용 -// return httpServletRequest.getRequestURI().contains("token"); + String token = request.getHeader("Authorization"); + return token == null || token.isEmpty(); } @Override @@ -47,15 +48,18 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private EncodedToken getAccessToken(HttpServletRequest request) { String accessToken = request.getHeader("Authorization"); - if (accessToken == null || accessToken.isEmpty()) { + if (!accessToken.startsWith("Bearer ")) { throw new JwtException(JwtErrorType.MISSING_TOKEN); } + + accessToken = accessToken.substring(7); + return new EncodedToken(accessToken); } private JwtAuthenticationToken createAuthenticationToken(Claims claims, EncodedToken accessToken) { String userId = claims.get("id", String.class); - UserRole role = claims.get("role", UserRole.class); + UserRole role = UserRole.valueOf(claims.get("role", String.class)); return new JwtAuthenticationToken( userId, From 0cff4f3b174ebcf9c71cd5b5228e00959cd5f0fe Mon Sep 17 00:00:00 2001 From: leebs0521 Date: Sat, 30 Nov 2024 17:44:30 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat(swagger):=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/configure/SwaggerConfig.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/java/com/somemore/global/configure/SwaggerConfig.java diff --git a/src/main/java/com/somemore/global/configure/SwaggerConfig.java b/src/main/java/com/somemore/global/configure/SwaggerConfig.java new file mode 100644 index 000000000..0ea82150a --- /dev/null +++ b/src/main/java/com/somemore/global/configure/SwaggerConfig.java @@ -0,0 +1,36 @@ +package com.somemore.global.configure; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI customOpenAPI() { + SecurityScheme securityScheme = new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .description("JWT 토큰을 이용한 인증"); + + SecurityRequirement securityRequirement = new SecurityRequirement() + .addList("AccessToken"); + + return new OpenAPI() + .info(new Info() + .title("Somemore API") + .version("1.0") + .description("Somemore swagger-ui 화면입니다.") + ) + .components(new Components() + .addSecuritySchemes("AccessToken", securityScheme) + ) + .addSecurityItem(securityRequirement); + } +} From 70723b64be7f75adde39bb545a1fb77763d374b9 Mon Sep 17 00:00:00 2001 From: leebs0521 Date: Sat, 30 Nov 2024 17:45:26 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat(center):=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/somemore/center/repository/CenterJpaRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/somemore/center/repository/CenterJpaRepository.java b/src/main/java/com/somemore/center/repository/CenterJpaRepository.java index fde29e33a..c68bb8441 100644 --- a/src/main/java/com/somemore/center/repository/CenterJpaRepository.java +++ b/src/main/java/com/somemore/center/repository/CenterJpaRepository.java @@ -9,4 +9,5 @@ public interface CenterJpaRepository extends JpaRepository { boolean existsById(UUID id); Optional
findCenterById(UUID id); + Optional
findByName(String name); } From ffb719fd4125d8ab6b3229d88df8ec13902b4171 Mon Sep 17 00:00:00 2001 From: leebs0521 Date: Sat, 30 Nov 2024 17:46:11 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat(security):=20=EB=94=94=EB=B2=84?= =?UTF-8?q?=EA=B9=85=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B8=B0=EA=B4=80=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=20=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/util/DevAccountSetUpConfig.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java diff --git a/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java b/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java new file mode 100644 index 000000000..c31f0ab1f --- /dev/null +++ b/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java @@ -0,0 +1,99 @@ +package com.somemore.auth.util; + +import static com.somemore.auth.oauth.OAuthProvider.NAVER; + +import com.somemore.auth.jwt.domain.EncodedToken; +import com.somemore.auth.jwt.domain.TokenType; +import com.somemore.auth.jwt.domain.UserRole; +import com.somemore.auth.jwt.generator.JwtGenerator; +import com.somemore.auth.jwt.refresh.domain.RefreshToken; +import com.somemore.auth.jwt.refresh.manager.RefreshTokenManager; +import com.somemore.center.domain.Center; +import com.somemore.center.repository.CenterJpaRepository; +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.repository.VolunteerJpaRepository; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class DevAccountSetUpConfig { + + private final VolunteerJpaRepository volunteerRepository; + private final CenterJpaRepository centerRepository; + private final JwtGenerator jwtGenerator; + private final RefreshTokenManager refreshTokenManager; + + private Volunteer volunteer; + private Center center; + + @Value("${app.develop.mode:false}") + private boolean developMode; + + @PostConstruct + public void generateAccessTokenForDev() { + if (!developMode) { + return; // 개발 모드에서만 실행 + } + + volunteer = Volunteer.createDefault(NAVER, "bongdari"); + center = Center.create( + "봉다리 자원봉사센터", + "02-1234-5678", + "", + "봉다리 기관 테스트 계정입니다.", + "https://somemore.bongdari.com", + "bongdari", + "1234" + ); + + volunteer = volunteerRepository.findByOauthId(volunteer.getOauthId()) + .orElseGet(() -> volunteerRepository.save(volunteer)); + + center = centerRepository.findByName(center.getName()) + .orElseGet(() -> centerRepository.save(center)); + + EncodedToken volunteerToken = saveRefreshTokenAndReturnAccessToken(volunteer.getId(), + UserRole.VOLUNTEER); + EncodedToken centerToken = saveRefreshTokenAndReturnAccessToken(center.getId(), + UserRole.CENTER); + + log.info("테스트용 봉사자 AccessToken: {}", volunteerToken.value()); + log.info("테스트용 기관 AccessToken: {}", centerToken.value()); + } + + @PreDestroy + public void cleanup() { + if (volunteer != null) { + refreshTokenManager.removeRefreshToken(volunteer.getId().toString()); + log.info("테스트용 AccessToken 제거, 봉사자 ID: {}", volunteer.getId()); + } + if (center != null) { + refreshTokenManager.removeRefreshToken(center.getId().toString()); + log.info("테스트용 AccessToken 제거, 기관 ID: {}", center.getId()); + } + } + + private EncodedToken saveRefreshTokenAndReturnAccessToken(UUID id, UserRole role) { + EncodedToken accessToken = generateToken(id, role, TokenType.ACCESS); + RefreshToken refreshToken = generateRefreshToken(id, role, accessToken); + refreshTokenManager.save(refreshToken); + return accessToken; + } + + private EncodedToken generateToken(UUID id, UserRole role, TokenType tokenType) { + return jwtGenerator.generateToken(id.toString(), role.name(), tokenType); + } + + private RefreshToken generateRefreshToken(UUID id, UserRole role, EncodedToken accessToken) { + return new RefreshToken(id.toString(), accessToken, + generateToken(id, role, TokenType.REFRESH)); + } +} + From 1333710b0daf08093b93e1f99bbf5d2f8222c040 Mon Sep 17 00:00:00 2001 From: leebs0521 Date: Sat, 30 Nov 2024 17:47:29 +0900 Subject: [PATCH 5/6] =?UTF-8?q?chore:=20=EB=94=94=EB=B2=84=EA=B9=85=20env?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 2 ++ src/test/resources/application-test.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6621c5d18..cdbad3892 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,8 @@ app: front-url: ${FRONT_URL} back-url: ${BACK_URL} + develop: + mode: ${APP_DEVELOP_MODE} # AWS S3 cloud: diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index 50d9922c6..d0d564d75 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -1,6 +1,8 @@ app: front-url: "http://localhost:3000" back-url: "http://localhost:8080" + develop: + mode: false spring: config: From fbc9de74d76f19511efa105afb18b98f27a113f3 Mon Sep 17 00:00:00 2001 From: leebs0521 Date: Sat, 30 Nov 2024 17:59:08 +0900 Subject: [PATCH 6/6] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/somemore/auth/jwt/filter/JwtAuthFilter.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java b/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java index 0fce0bbe3..071cf7677 100644 --- a/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java +++ b/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java @@ -9,6 +9,8 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; @@ -17,10 +19,6 @@ import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; -import java.io.IOException; -import java.util.List; -import software.amazon.awssdk.services.s3.endpoints.internal.Value.Str; - @RequiredArgsConstructor @Slf4j @Component @@ -35,7 +33,8 @@ protected boolean shouldNotFilter(HttpServletRequest request) { } @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { EncodedToken accessToken = getAccessToken(request); jwtUseCase.processAccessToken(accessToken, response); @@ -57,7 +56,8 @@ private EncodedToken getAccessToken(HttpServletRequest request) { return new EncodedToken(accessToken); } - private JwtAuthenticationToken createAuthenticationToken(Claims claims, EncodedToken accessToken) { + private JwtAuthenticationToken createAuthenticationToken(Claims claims, + EncodedToken accessToken) { String userId = claims.get("id", String.class); UserRole role = UserRole.valueOf(claims.get("role", String.class));