-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1616 from woowacourse/feature/1612-modify-loginIn…
…terceptor 로그인 Interceptor 개선
- Loading branch information
Showing
10 changed files
with
266 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 4 additions & 36 deletions
40
backend/src/main/java/wooteco/prolog/login/ui/LoginInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,26 @@ | ||
package wooteco.prolog.login.ui; | ||
|
||
import java.util.Objects; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import lombok.AllArgsConstructor; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.web.servlet.HandlerInterceptor; | ||
import wooteco.prolog.login.application.AuthorizationExtractor; | ||
import wooteco.prolog.login.application.GithubLoginService; | ||
import wooteco.support.autoceptor.AuthenticationDetector; | ||
|
||
@AllArgsConstructor | ||
public class LoginInterceptor implements HandlerInterceptor { | ||
|
||
private static final String ORIGIN = "Origin"; | ||
private static final String ACCESS_REQUEST_METHOD = "Access-Control-Request-Method"; | ||
private static final String ACCESS_REQUEST_HEADERS = "Access-Control-Request-Headers"; | ||
|
||
private final GithubLoginService githubLoginService; | ||
private final AuthenticationDetector authenticationDetector; | ||
|
||
@Override | ||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, | ||
Object handler) { | ||
if (isPreflighted(request)) { | ||
return true; | ||
} | ||
|
||
if (HttpMethod.GET.matches(request.getMethod())) { | ||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { | ||
if (!authenticationDetector.requireLogin(request)) { | ||
return true; | ||
} | ||
|
||
githubLoginService.validateToken(AuthorizationExtractor.extract(request)); | ||
return true; | ||
} | ||
|
||
private boolean isPreflighted(HttpServletRequest request) { | ||
return isOptionsMethod(request) | ||
&& hasOrigin(request) | ||
&& hasRequestHeaders(request) | ||
&& hasRequestMethods(request); | ||
} | ||
|
||
public boolean isOptionsMethod(HttpServletRequest request) { | ||
return HttpMethod.OPTIONS.matches(request.getMethod()); | ||
} | ||
|
||
public boolean hasOrigin(HttpServletRequest request) { | ||
return Objects.nonNull(request.getHeader(ORIGIN)); | ||
} | ||
|
||
public boolean hasRequestMethods(HttpServletRequest request) { | ||
return Objects.nonNull(request.getHeader(ACCESS_REQUEST_METHOD)); | ||
} | ||
|
||
public boolean hasRequestHeaders(HttpServletRequest request) { | ||
return Objects.nonNull(request.getHeader(ACCESS_REQUEST_HEADERS)); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
backend/src/main/java/wooteco/support/autoceptor/AuthenticationDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package wooteco.support.autoceptor; | ||
|
||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import javax.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpMethod; | ||
|
||
@RequiredArgsConstructor | ||
public class AuthenticationDetector { | ||
|
||
private static final String ORIGIN = "Origin"; | ||
private static final String ACCESS_REQUEST_METHOD = "Access-Control-Request-Method"; | ||
private static final String ACCESS_REQUEST_HEADERS = "Access-Control-Request-Headers"; | ||
|
||
private final List<MethodPattern> requireLoginPatterns; | ||
|
||
public boolean requireLogin(HttpServletRequest request) { | ||
if (isPreflighted(request)) { | ||
return false; | ||
} | ||
|
||
if (HttpMethod.GET.matches(request.getMethod())) { | ||
return false; | ||
} | ||
|
||
return requireLoginPatterns.stream() | ||
.anyMatch(pattern -> pattern.match(request)); | ||
} | ||
|
||
private boolean isPreflighted(HttpServletRequest request) { | ||
return isOptionsMethod(request) | ||
&& hasOrigin(request) | ||
&& hasRequestHeaders(request) | ||
&& hasRequestMethods(request); | ||
} | ||
|
||
private boolean isOptionsMethod(HttpServletRequest request) { | ||
return HttpMethod.OPTIONS.matches(request.getMethod()); | ||
} | ||
|
||
private boolean hasOrigin(HttpServletRequest request) { | ||
return Objects.nonNull(request.getHeader(ORIGIN)); | ||
} | ||
|
||
private boolean hasRequestMethods(HttpServletRequest request) { | ||
return Objects.nonNull(request.getHeader(ACCESS_REQUEST_METHOD)); | ||
} | ||
|
||
private boolean hasRequestHeaders(HttpServletRequest request) { | ||
return Objects.nonNull(request.getHeader(ACCESS_REQUEST_HEADERS)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
backend/src/main/java/wooteco/support/autoceptor/MethodPattern.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package wooteco.support.autoceptor; | ||
|
||
import java.util.regex.Pattern; | ||
import javax.servlet.http.HttpServletRequest; | ||
import org.springframework.http.HttpMethod; | ||
|
||
public class MethodPattern { | ||
|
||
private static final String INVALID_METHOD_PATTERN_MESSAGE = "uri 와 method 가 지정되지 않은 MethodPattern 이 있습니다. method : %s, uri : %s"; | ||
|
||
private final HttpMethod method; | ||
private final Pattern pattern; | ||
|
||
public MethodPattern(HttpMethod method, String uri) { | ||
validate(uri, method); | ||
this.method = method; | ||
this.pattern = convertToPattern(uri); | ||
} | ||
|
||
private Pattern convertToPattern(String uri) { | ||
String replace = uri.replace("*", "[^/]+"); | ||
String regex = "^" + replace + "$"; | ||
return Pattern.compile(regex); | ||
} | ||
|
||
private void validate(String method, HttpMethod uri) { | ||
if (uri == null || method == null) { | ||
throw new IllegalArgumentException(String.format(INVALID_METHOD_PATTERN_MESSAGE, method, uri)); | ||
} | ||
} | ||
|
||
public boolean match(HttpServletRequest request) { | ||
if (!pattern.matcher(request.getRequestURI()).matches()) { | ||
return false; | ||
} | ||
if (!method.matches(request.getMethod())) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
backend/src/test/java/wooteco/support/autoceptor/MethodPatternTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package wooteco.support.autoceptor; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.mockito.BDDMockito.given; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import org.junit.jupiter.api.DisplayNameGeneration; | ||
import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
import org.mockito.Mockito; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.http.HttpMethod; | ||
|
||
@DisplayNameGeneration(ReplaceUnderscores.class) | ||
@SuppressWarnings("NonAsciiCharacters") | ||
@ExtendWith(MockitoExtension.class) | ||
class MethodPatternTest { | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"/path1/param1/path2", "/path1/123123/path2"}) | ||
void matching(String requestUri) { | ||
// given | ||
MethodPattern methodPattern = new MethodPattern(HttpMethod.GET, "/path1/*/path2"); | ||
HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class); | ||
given(mockRequest.getMethod()) | ||
.willReturn(HttpMethod.GET.name()); | ||
given(mockRequest.getRequestURI()) | ||
.willReturn(requestUri); | ||
|
||
// when | ||
boolean mathcing = methodPattern.match(mockRequest); | ||
|
||
// then | ||
assertThat(mathcing).isTrue(); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"/path1/param1/path2/path3", "/path1/path2"}) | ||
void notMatching(String requestUri) { | ||
// given | ||
MethodPattern methodPattern = new MethodPattern(HttpMethod.GET, "/path1/*/path2"); | ||
HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class); | ||
given(mockRequest.getRequestURI()) | ||
.willReturn(requestUri); | ||
|
||
// when | ||
boolean mathcing = methodPattern.match(mockRequest); | ||
|
||
// then | ||
assertThat(mathcing).isFalse(); | ||
} | ||
} |
Oops, something went wrong.