diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/config/PermitAllEndpoint.java b/src/main/java/org/guzzing/studayserver/domain/auth/config/PermitAllEndpoint.java index c8652d0b..9ae1c461 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/config/PermitAllEndpoint.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/config/PermitAllEndpoint.java @@ -7,7 +7,8 @@ private PermitAllEndpoint() { protected static final String[] permitAllArray = new String[]{ "/", - "/auth/**", + "/auth/kakao", + "/auth/google", "/error", "/docs/**", "/favicon.ico", diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/config/SecurityConfig.java b/src/main/java/org/guzzing/studayserver/domain/auth/config/SecurityConfig.java index e6b68e91..493a0a86 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/config/SecurityConfig.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/config/SecurityConfig.java @@ -3,10 +3,7 @@ import java.util.List; import java.util.stream.Stream; import org.guzzing.studayserver.domain.auth.exception.SecurityExceptionHandlerFilter; -import org.guzzing.studayserver.domain.auth.jwt.AuthTokenProvider; import org.guzzing.studayserver.domain.auth.jwt.JwtAuthenticationFilter; -import org.guzzing.studayserver.domain.auth.jwt.logout.LogoutAuthenticationFilter; -import org.guzzing.studayserver.domain.auth.service.AuthService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -26,23 +23,20 @@ @EnableWebSecurity public class SecurityConfig { - private final AuthTokenProvider authTokenProvider; - private final AuthService authService; private final SecurityExceptionHandlerFilter securityExceptionHandlerFilter; + private final JwtAuthenticationFilter jwtTokenValidationFilter; - public SecurityConfig(AuthTokenProvider authTokenProvider, AuthService authService, - SecurityExceptionHandlerFilter securityExceptionHandlerFilter) { - this.authTokenProvider = authTokenProvider; - this.authService = authService; + public SecurityConfig( + SecurityExceptionHandlerFilter securityExceptionHandlerFilter, + JwtAuthenticationFilter jwtTokenValidationFilter + ) { this.securityExceptionHandlerFilter = securityExceptionHandlerFilter; + this.jwtTokenValidationFilter = jwtTokenValidationFilter; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - JwtAuthenticationFilter jwtTokenValidationFilter = new JwtAuthenticationFilter(authTokenProvider); - LogoutAuthenticationFilter logoutAuthenticationFilter = new LogoutAuthenticationFilter(authService); - - http + return http .authorizeHttpRequests(request -> request .requestMatchers( Stream @@ -58,10 +52,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .httpBasic(HttpBasicConfigurer::disable) .formLogin(AbstractHttpConfigurer::disable) .addFilterBefore(jwtTokenValidationFilter, UsernamePasswordAuthenticationFilter.class) - .addFilterBefore(logoutAuthenticationFilter, JwtAuthenticationFilter.class) - .addFilterBefore(securityExceptionHandlerFilter, LogoutAuthenticationFilter.class); - - return http.build(); + .addFilterBefore(securityExceptionHandlerFilter, JwtAuthenticationFilter.class) + .build(); } @Bean diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/controller/AuthController.java b/src/main/java/org/guzzing/studayserver/domain/auth/controller/AuthController.java index 67ee08cd..585321c2 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/controller/AuthController.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/controller/AuthController.java @@ -63,9 +63,7 @@ public ResponseEntity googleAuthRequest(HttpServletRequest re } @GetMapping("/refresh") - public ResponseEntity refreshToken( - HttpServletRequest request, - @MemberId Long memberId) { + public ResponseEntity refreshToken(HttpServletRequest request, @MemberId Long memberId) { String appToken = JwtHeaderUtil.getAccessToken(request); AuthToken authToken = authTokenProvider.convertAuthToken(appToken); @@ -77,8 +75,7 @@ public ResponseEntity refreshToken( } @DeleteMapping("/logout") - public ResponseEntity logout( - HttpServletRequest request) { + public ResponseEntity logout(HttpServletRequest request) { String appToken = JwtHeaderUtil.getAccessToken(request); AuthToken authToken = authTokenProvider.convertAuthToken(appToken); diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthToken.java b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthToken.java index 9947bf30..8b26395d 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthToken.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthToken.java @@ -30,16 +30,16 @@ public class AuthToken { @Builder AuthToken(String socialId, String role, Long memberId, Date expiry, Key key) { - this.token = createAccessToken(socialId, role, memberId, expiry); + this.token = createAccessToken(socialId, role, memberId, expiry, key); this.key = key; } AuthToken(Date expiry, Key key) { - this.token = createRefreshToken(expiry); + this.token = createRefreshToken(expiry, key); this.key = key; } - private String createAccessToken(String socialId, String role, Long id, Date expiry) { + private String createAccessToken(String socialId, String role, Long id, Date expiry, Key key) { return Jwts .builder() .setSubject(socialId) @@ -50,7 +50,7 @@ private String createAccessToken(String socialId, String role, Long id, Date exp .compact(); } - private String createRefreshToken(Date expiry) { + private String createRefreshToken(Date expiry, Key key) { Claims claims = Jwts .claims(); diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthTokenProvider.java b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthTokenProvider.java index 706995b1..284aa0bf 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthTokenProvider.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/AuthTokenProvider.java @@ -13,7 +13,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Component; -@Slf4j @Component public class AuthTokenProvider { diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/JwtAuthenticationFilter.java b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/JwtAuthenticationFilter.java index 37af0810..ea7e9ce1 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/JwtAuthenticationFilter.java @@ -5,24 +5,28 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; +import org.guzzing.studayserver.domain.auth.service.AuthService; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +@Component public class JwtAuthenticationFilter extends OncePerRequestFilter { private static final String HEADER_AUTHORIZATION = "Authorization"; private static final String TOKEN_PREFIX = "Bearer "; private final AuthTokenProvider tokenProvider; + private final AuthService authService; - public JwtAuthenticationFilter(AuthTokenProvider tokenProvider) { + public JwtAuthenticationFilter(AuthTokenProvider tokenProvider, AuthService authService) { this.tokenProvider = tokenProvider; + this.authService = authService; } @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { final String AUTHORIZATION_HEADER = request.getHeader(HEADER_AUTHORIZATION); @@ -31,13 +35,10 @@ protected void doFilterInternal(HttpServletRequest request, String tokenStr = JwtHeaderUtil.getAccessToken(request); AuthToken token = tokenProvider.convertAuthToken(tokenStr); - if (token.isValidTokenClaims()) { + if (token.isValidTokenClaims() && !authService.isLogout(token.getToken())) { Authentication authentication = tokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); } - - filterChain.doFilter(request, response); - return; } filterChain.doFilter(request, response); diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/logout/LogoutAuthenticationFilter.java b/src/main/java/org/guzzing/studayserver/domain/auth/jwt/logout/LogoutAuthenticationFilter.java deleted file mode 100644 index 1b6623f6..00000000 --- a/src/main/java/org/guzzing/studayserver/domain/auth/jwt/logout/LogoutAuthenticationFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.guzzing.studayserver.domain.auth.jwt.logout; - -import static org.guzzing.studayserver.global.error.response.ErrorCode.IS_LOGOUT_TOKEN; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import org.guzzing.studayserver.domain.auth.exception.TokenIsLogoutException; -import org.guzzing.studayserver.domain.auth.jwt.JwtHeaderUtil; -import org.guzzing.studayserver.domain.auth.service.AuthService; -import org.springframework.web.filter.OncePerRequestFilter; - -public class LogoutAuthenticationFilter extends OncePerRequestFilter { - - private static final String HEADER_AUTHORIZATION = "Authorization"; - private static final String TOKEN_PREFIX = "Bearer "; - - private final AuthService authService; - - public LogoutAuthenticationFilter(AuthService authService) { - this.authService = authService; - } - - @Override - protected void doFilterInternal( - HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain - ) throws ServletException, IOException { - - final String AUTHORIZATION_HEADER = request.getHeader(HEADER_AUTHORIZATION); - - if (AUTHORIZATION_HEADER != null && AUTHORIZATION_HEADER.startsWith(TOKEN_PREFIX)) { - String token = JwtHeaderUtil.getAccessToken(request); - - boolean isLogout = authService.isLogout(token); - - if (isLogout) { - throw new TokenIsLogoutException(IS_LOGOUT_TOKEN); - } - } - - filterChain.doFilter(request, response); - } - -} diff --git a/src/main/java/org/guzzing/studayserver/domain/auth/service/AuthService.java b/src/main/java/org/guzzing/studayserver/domain/auth/service/AuthService.java index 9cabc549..8f905318 100644 --- a/src/main/java/org/guzzing/studayserver/domain/auth/service/AuthService.java +++ b/src/main/java/org/guzzing/studayserver/domain/auth/service/AuthService.java @@ -3,7 +3,6 @@ import static org.guzzing.studayserver.global.error.response.ErrorCode.EXPIRED_REFRESH_TOKEN; import io.jsonwebtoken.Claims; -import lombok.extern.slf4j.Slf4j; import org.guzzing.studayserver.domain.auth.exception.TokenExpiredException; import org.guzzing.studayserver.domain.auth.jwt.AuthToken; import org.guzzing.studayserver.domain.auth.jwt.AuthTokenProvider; @@ -13,7 +12,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -@Slf4j @Service public class AuthService { @@ -45,6 +43,7 @@ public AuthRefreshResult updateAccessToken(AuthToken accessToken, Long memberId) validateRefreshToken(accessToken.getToken()); + jwtCacheRepository.delete(accessToken.getToken()); AuthToken newAccessToken = saveAccessToken(memberId, socialId); return AuthRefreshResult.of(newAccessToken.getToken(), memberId); @@ -53,7 +52,6 @@ public AuthRefreshResult updateAccessToken(AuthToken accessToken, Long memberId) @Transactional public AuthLogoutResult logout(AuthToken authToken) { jwtCacheRepository.delete(authToken.getToken()); - return new AuthLogoutResult(true); } diff --git a/src/main/java/org/guzzing/studayserver/global/log/LoggingAspect.java b/src/main/java/org/guzzing/studayserver/global/log/LoggingAspect.java index 7fb1ca86..cbed5e58 100644 --- a/src/main/java/org/guzzing/studayserver/global/log/LoggingAspect.java +++ b/src/main/java/org/guzzing/studayserver/global/log/LoggingAspect.java @@ -15,8 +15,8 @@ @Component public class LoggingAspect { - private static final String FORMAT = "invoke method : {} - {} ({}) / elapsed time : {}"; - private static final double MILLI_SECOND_TO_SECOND_UNIT = 1; + private static final String FORMAT = "invoke method : {} - {} / elapsed time : {}\nrequest url : {}"; + private static final double MILLI_SECOND_TO_SECOND_UNIT = 0.001; private static final double MAX_AFFORDABLE_TIME = 2; @@ -39,8 +39,6 @@ public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable { return proceed; //메소드의 결과를 반환해주는 이유는 aop가 프록시로 구현되기 때문이다. 프록시 객체가 원본 객체와 동일하게 결과를 반환해야 하기 때문에 여기서 원본 객체의 결과(proceed)를 return해줘야 프록시 객체가 원본 객체와 동일하게 작동할 수 있다. } - log.info(FORMAT, className, methodName, elapsedTime, requestUrl); - return proceed; } diff --git a/src/test/java/org/guzzing/studayserver/domain/calendar/controller/AcademyCalendarControllerTest.java b/src/test/java/org/guzzing/studayserver/domain/calendar/controller/AcademyCalendarControllerTest.java index bc5b3bc0..224bd1fa 100644 --- a/src/test/java/org/guzzing/studayserver/domain/calendar/controller/AcademyCalendarControllerTest.java +++ b/src/test/java/org/guzzing/studayserver/domain/calendar/controller/AcademyCalendarControllerTest.java @@ -23,12 +23,19 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; -@WebMvcTest(AcademyCalendarController.class) +@AutoConfigureMockMvc +@AutoConfigureRestDocs +@SpringBootTest +@Transactional class AcademyCalendarControllerTest { @Autowired @@ -37,12 +44,6 @@ class AcademyCalendarControllerTest { @Autowired private ObjectMapper objectMapper; - @MockBean - private AcademyCalendarService academyCalendarService; - - @MockBean - private AcademyCalendarFacade academyCalendarFacade; - @DisplayName(" 예외가 발생하는 상황을 검증한다.") @Nested class ThrowException { diff --git a/src/test/java/org/guzzing/studayserver/domain/child/controller/ChildRestControllerTest.java b/src/test/java/org/guzzing/studayserver/domain/child/controller/ChildRestControllerTest.java index 936edc6d..3c38eb55 100644 --- a/src/test/java/org/guzzing/studayserver/domain/child/controller/ChildRestControllerTest.java +++ b/src/test/java/org/guzzing/studayserver/domain/child/controller/ChildRestControllerTest.java @@ -48,6 +48,7 @@ import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; @@ -56,9 +57,9 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.web.multipart.MultipartFile; -@WebMvcTest(ChildRestController.class) @AutoConfigureRestDocs @AutoConfigureMockMvc(addFilters = false) +@SpringBootTest class ChildRestControllerTest { private static final String TAG = "아이 API"; diff --git a/src/test/java/org/guzzing/studayserver/domain/member/controller/MemberRestControllerTest.java b/src/test/java/org/guzzing/studayserver/domain/member/controller/MemberRestControllerTest.java index fde4fb46..8c594b7a 100644 --- a/src/test/java/org/guzzing/studayserver/domain/member/controller/MemberRestControllerTest.java +++ b/src/test/java/org/guzzing/studayserver/domain/member/controller/MemberRestControllerTest.java @@ -26,15 +26,20 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; -@WebMvcTest(MemberRestController.class) -@AutoConfigureMockMvc(addFilters = false) +@AutoConfigureRestDocs +@AutoConfigureMockMvc +@SpringBootTest +@Transactional class MemberRestControllerTest { @Autowired @@ -42,8 +47,6 @@ class MemberRestControllerTest { @MockBean private MemberService memberService; - @MockBean - private MemberFacade memberFacade; @Autowired private ObjectMapper objectMapper; diff --git a/src/test/java/org/guzzing/studayserver/domain/review/controller/ReviewRestControllerTest.java b/src/test/java/org/guzzing/studayserver/domain/review/controller/ReviewRestControllerTest.java index 51968d15..b700bfcd 100644 --- a/src/test/java/org/guzzing/studayserver/domain/review/controller/ReviewRestControllerTest.java +++ b/src/test/java/org/guzzing/studayserver/domain/review/controller/ReviewRestControllerTest.java @@ -26,9 +26,9 @@ import org.guzzing.studayserver.domain.academy.repository.review.ReviewCountRepository; import org.guzzing.studayserver.domain.member.repository.MemberRepository; import org.guzzing.studayserver.domain.review.controller.dto.request.ReviewPostRequest; -import org.guzzing.studayserver.domain.review.fixture.ReviewFixture; import org.guzzing.studayserver.testutil.fixture.academy.AcademyFixture; import org.guzzing.studayserver.testutil.fixture.member.MemberFixture; +import org.guzzing.studayserver.testutil.fixture.review.ReviewFixture; import org.guzzing.studayserver.testutil.security.WithMockCustomOAuth2LoginUser; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/org/guzzing/studayserver/domain/review/service/ReviewFacadeTest.java b/src/test/java/org/guzzing/studayserver/domain/review/service/ReviewFacadeTest.java index 37604fcc..26f52b5a 100644 --- a/src/test/java/org/guzzing/studayserver/domain/review/service/ReviewFacadeTest.java +++ b/src/test/java/org/guzzing/studayserver/domain/review/service/ReviewFacadeTest.java @@ -13,13 +13,13 @@ import org.guzzing.studayserver.domain.academy.repository.review.ReviewCountRepository; import org.guzzing.studayserver.domain.member.model.Member; import org.guzzing.studayserver.domain.member.repository.MemberRepository; -import org.guzzing.studayserver.domain.review.fixture.ReviewFixture; import org.guzzing.studayserver.domain.review.model.ReviewType; import org.guzzing.studayserver.domain.review.service.dto.request.ReviewPostParam; import org.guzzing.studayserver.domain.review.service.dto.response.ReviewPostResult; import org.guzzing.studayserver.domain.review.service.dto.response.ReviewableResult; import org.guzzing.studayserver.testutil.fixture.academy.AcademyFixture; import org.guzzing.studayserver.testutil.fixture.member.MemberFixture; +import org.guzzing.studayserver.testutil.fixture.review.ReviewFixture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/guzzing/studayserver/domain/review/fixture/ReviewFixture.java b/src/test/java/org/guzzing/studayserver/testutil/fixture/review/ReviewFixture.java similarity index 97% rename from src/test/java/org/guzzing/studayserver/domain/review/fixture/ReviewFixture.java rename to src/test/java/org/guzzing/studayserver/testutil/fixture/review/ReviewFixture.java index 191ec70a..391f56ec 100644 --- a/src/test/java/org/guzzing/studayserver/domain/review/fixture/ReviewFixture.java +++ b/src/test/java/org/guzzing/studayserver/testutil/fixture/review/ReviewFixture.java @@ -1,4 +1,4 @@ -package org.guzzing.studayserver.domain.review.fixture; +package org.guzzing.studayserver.testutil.fixture.review; import static org.guzzing.studayserver.domain.review.model.ReviewType.CHEAP_FEE; import static org.guzzing.studayserver.domain.review.model.ReviewType.GOOD_FACILITY;