Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: interceptor http method도 지정하게 변경 #588

Open
wants to merge 2 commits into
base: BE/develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions backend/src/main/java/com/yigongil/backend/config/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.yigongil.backend.config;

import static com.yigongil.backend.config.auth.path.HttpMethod.ANY;
import static com.yigongil.backend.config.auth.path.HttpMethod.GET;
import static com.yigongil.backend.config.auth.path.HttpMethod.POST;
import static com.yigongil.backend.config.auth.path.HttpMethod.PUT;

import com.yigongil.backend.config.auth.AuthInterceptor;
import com.yigongil.backend.config.auth.MemberArgumentResolver;
import com.yigongil.backend.config.auth.path.PathInterceptor;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

Expand All @@ -21,20 +28,25 @@ public AuthConfig(MemberArgumentResolver memberArgumentResolver, AuthInterceptor

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login/github/tokens")
.excludePathPatterns("/login/tokens/refresh")
.excludePathPatterns("/login/fake/tokens")
.excludePathPatterns("/members/{id:[0-9]\\d*}")
.excludePathPatterns("/members/exists")
.excludePathPatterns("/api/**")
.excludePathPatterns("/api-docs/**")
.excludePathPatterns("/swagger-ui/**")
.excludePathPatterns("/actuator/**")
.excludePathPatterns("/fake/proceed")
.excludePathPatterns("/studies/{id:[0-9]\\d*}/rounds/{id:[0-9]\\d*}/progress-rate");
registry.addInterceptor(loginInterceptor());
}

private HandlerInterceptor loginInterceptor() {
return new PathInterceptor(authInterceptor)
.includePath("/**", ANY)
.excludePath("/login/github/tokens", GET)
.excludePath("/login/tokens/refresh", POST)
.excludePath("/login/fake/tokens", GET)
.excludePath("/members/{id:[0-9]\\d*}", GET)
.excludePath("/members/exists", GET)
.excludePath("/members", GET)
.excludePath("/api/**", GET)
.excludePath("/api-docs/**", GET)
.excludePath("/swagger-ui/**", GET)
.excludePath("/actuator/**", GET)
.excludePath("/fake/proceed", PUT)
.excludePath("/studies", GET)
.excludePath("/studies/{id:[0-9]\\d*}", GET);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.yigongil.backend.config.auth;

import com.yigongil.backend.exception.InvalidTokenException;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
Expand All @@ -11,8 +10,6 @@
@Component
public class AuthInterceptor implements HandlerInterceptor {

private static final Pattern STUDY_DETAIL_REQUEST_PATTERN = Pattern.compile("/studies/[1-9]\\d*");

private final JwtTokenProvider jwtTokenProvider;
private final AuthContext authContext;

Expand All @@ -24,9 +21,6 @@ public AuthInterceptor(JwtTokenProvider jwtTokenProvider, AuthContext authContex
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if (isExcludedMethodAndUri(request)) {
return true;
}

if (authHeader == null) {
throw new InvalidTokenException("인증 정보가 없습니다. 입력된 token: ", null);
Expand All @@ -35,14 +29,4 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
authContext.setMemberId(memberId);
return true;
}

private boolean isExcludedMethodAndUri(HttpServletRequest request) {
if (request.getMethod().equals("GET") && STUDY_DETAIL_REQUEST_PATTERN.matcher(request.getRequestURI()).matches()) {
return true;
}
if (request.getMethod().equals("GET") && request.getRequestURI().equals("/studies")) {
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.yigongil.backend.config.auth.path;

public enum HttpMethod {

PUT,
POST,
GET,
PATCH,
DELETE,
ANY {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍

@Override
public boolean matches(String method) {
return true;
}
};

public boolean matches(String method) {
return name().equalsIgnoreCase(method);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.yigongil.backend.config.auth.path;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

public class PathContainer {

private final PathMatcher pathMatcher = new AntPathMatcher();
private final List<PathPattern> includedPaths = new ArrayList<>();
private final List<PathPattern> excludedPaths = new ArrayList<>();

public PathContainer excludePath(String path, HttpMethod... httpMethods) {
excludedPaths.add(new PathPattern(path, Set.of(httpMethods)));

return this;
}

public PathContainer includePath(String path, HttpMethod... httpMethods) {
includedPaths.add(new PathPattern(path, Set.of(httpMethods)));

return this;
}

public boolean isNotInclude(String path, String method) {
boolean isExcludedPath = excludedPaths.stream()
.anyMatch(pathPattern -> pathPattern.matches(pathMatcher, path, method));

boolean isNotIncludePath = includedPaths.stream()
.noneMatch(pathPattern -> pathPattern.matches(pathMatcher, path, method));

return isExcludedPath || isNotIncludePath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.yigongil.backend.config.auth.path;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;

public class PathInterceptor implements HandlerInterceptor {

private final PathContainer pathContainer = new PathContainer();
private final HandlerInterceptor handlerInterceptor;

public PathInterceptor(HandlerInterceptor handlerInterceptor) {
this.handlerInterceptor = handlerInterceptor;
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String method = request.getMethod();
String uri = request.getRequestURI();

if (pathContainer.isNotInclude(uri, method)) {
return true;
}

return handlerInterceptor.preHandle(request, response, handler);
}

public PathInterceptor includePath(String path, HttpMethod... methods) {
pathContainer.includePath(path, methods);

return this;
}

public PathInterceptor excludePath(String path, HttpMethod... methods) {
pathContainer.excludePath(path, methods);

return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.yigongil.backend.config.auth.path;

import java.util.Set;
import org.springframework.util.PathMatcher;

public class PathPattern {

private final String path;
private final Set<HttpMethod> httpMethods;

public PathPattern(String path, Set<HttpMethod> httpMethods) {
this.path = path;
this.httpMethods = httpMethods;
}

public boolean matches(PathMatcher pathMatcher, String targetPath, String pathMethod) {
return pathMatcher.match(path, targetPath) && matchesMethod(pathMethod);
}

private boolean matchesMethod(String pathMethod) {
return httpMethods.stream()
.anyMatch(httpMethod -> httpMethod.matches(pathMethod));
}
}