Skip to content

Commit

Permalink
Merge pull request #139 from Guzzing/fix/quit
Browse files Browse the repository at this point in the history
[Fix/quit] 토큰 기반 로그아웃 방식 변경
  • Loading branch information
onetuks authored Jan 16, 2024
2 parents 06d47ca + ba2b12a commit b0adb27
Show file tree
Hide file tree
Showing 15 changed files with 48 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ private PermitAllEndpoint() {

protected static final String[] permitAllArray = new String[]{
"/",
"/auth/**",
"/auth/kakao",
"/auth/google",
"/error",
"/docs/**",
"/favicon.ico",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ public ResponseEntity<AuthLoginResponse> googleAuthRequest(HttpServletRequest re
}

@GetMapping("/refresh")
public ResponseEntity<AuthRefreshResponse> refreshToken(
HttpServletRequest request,
@MemberId Long memberId) {
public ResponseEntity<AuthRefreshResponse> refreshToken(HttpServletRequest request, @MemberId Long memberId) {

String appToken = JwtHeaderUtil.getAccessToken(request);
AuthToken authToken = authTokenProvider.convertAuthToken(appToken);
Expand All @@ -77,8 +75,7 @@ public ResponseEntity<AuthRefreshResponse> refreshToken(
}

@DeleteMapping("/logout")
public ResponseEntity<AuthLogoutResponse> logout(
HttpServletRequest request) {
public ResponseEntity<AuthLogoutResponse> logout(HttpServletRequest request) {
String appToken = JwtHeaderUtil.getAccessToken(request);
AuthToken authToken = authTokenProvider.convertAuthToken(appToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class AuthTokenProvider {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -13,7 +12,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class AuthService {

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand All @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -37,12 +44,6 @@ class AcademyCalendarControllerTest {
@Autowired
private ObjectMapper objectMapper;

@MockBean
private AcademyCalendarService academyCalendarService;

@MockBean
private AcademyCalendarFacade academyCalendarFacade;

@DisplayName(" 예외가 발생하는 상황을 검증한다.")
@Nested
class ThrowException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,27 @@
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
private MockMvc mockMvc;

@MockBean
private MemberService memberService;
@MockBean
private MemberFacade memberFacade;

@Autowired
private ObjectMapper objectMapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down

0 comments on commit b0adb27

Please sign in to comment.