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..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,9 +19,6 @@ import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; -import java.io.IOException; -import java.util.List; - @RequiredArgsConstructor @Slf4j @Component @@ -29,12 +28,13 @@ 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 - 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); @@ -47,15 +47,19 @@ 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) { + 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, 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)); + } +} + 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); } 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); + } +} 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: