[OAuth 2.0] 3번 브라우저의 GET or POST - doFilterInternal

다음 코드는 이 HTTP 요청이 OAuth 인가 엔드포인트 요청인가?를 판단하는 조건 객체다.

private final RequestMatcher authorizationEndpointMatcher;

HttpServletRequest → true / false 를 반환하는 판별기

 

 

생성자

public class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilter {

    /**
     * 이 HTTP 요청이 OAuth 인가 엔드포인트 요청인가?”를 판단하는 조건 객체
     */
    private final RequestMatcher authorizationEndpointMatcher;

    public OAuth2AuthorizationEndpointFilter(String authorizationEndpointUri) {
        /**
         * 어떤 HTTP 요청을 /oauth2/authorize 인가 요청으로 볼 것인가?를 정의하는 요청 판별기(RequestMatcher) 즉, 이 Filter 언제
         * 동작해야하는지 결정하는 규칙
         */
        this.authorizationEndpointMatcher = createDefaultRequestMatcher(authorizationEndpointUri);
    }
  • 위 코드를 보면 createDefaultRequestMatcher라는 메소드를 통해 무엇을 하게 됨

 

createDefaultRequestMatcher

  • 어떤 HTTP 요청을 OAuth 인가 엔드포인트 요청으로 볼 것인가를 정확하게 정의하는 판별기(factory)다.

Authorization Endpoint에는 서로 다른 2가지 종류의 요청이 들어옴

  1. 인가 요청 (Authorization Request)
  2. 동의 제출 요청 (Consent Submission)

→ 하지만 URL은 동일함 그래서 HTTP Method 및 파라미터 조합으로 판별

 

이 메소드를 분석해보자

private static RequestMatcher createDefaultRequestMatcher(String authorizationEndpointUri) {
    /**
     *  GET /oauth2/authorize
     * 	OAuth 인가 요청의 기본 형태 (RFC 6749 3.1)
     */
    RequestMatcher authorizationRequestGetMatcher = PathPatternRequestMatcher.withDefaults()
            .matcher(HttpMethod.GET, authorizationEndpointUri);

    /**
     * POST는 두 가지 의미
     * 인가 요청
     * 동의 제출
     * 파라미터를 봐야함 -> 다음 코드에서 response_type을 보게됨
     */
    RequestMatcher authorizationRequestPostMatcher = PathPatternRequestMatcher.withDefaults()
            .matcher(HttpMethod.POST, authorizationEndpointUri);

    /**
     *  response_type 파라미터 있는지 검사
     *  response_type이 있으면 → 인가 요청
     * 	response_type이 없으면 → 동의(consent) 제출 요청
     */
    RequestMatcher responseTypeParameterMatcher = (
            request) -> request.getParameter(OAuth2ParameterNames.RESPONSE_TYPE) != null;

    /**
     * 인가 요청 =
     *   GET  /oauth2/authorize
     *   OR
     *   POST /oauth2/authorize + response_type 있음
     */
    RequestMatcher authorizationRequestMatcher = new OrRequestMatcher(authorizationRequestGetMatcher,
            new AndRequestMatcher(authorizationRequestPostMatcher, responseTypeParameterMatcher));

    /**
     * 동의 제출 =
     *   POST /oauth2/authorize
     *   AND response_type 없음
     */
    RequestMatcher authorizationConsentMatcher = new AndRequestMatcher(authorizationRequestPostMatcher,
            new NegatedRequestMatcher(responseTypeParameterMatcher));

    /**
     *  최종 결론: 둘 다 인가 엔드포인트 요청이다
     *  즉 이 Filter는 최초 인가 요청, 동의 제출 요청
     * -> 둘 다 처리한다
     */
    return new OrRequestMatcher(authorizationRequestMatcher, authorizationConsentMatcher);
}

우리는 일단 최초 요청만 처리할 거임 그래서 다음과 같이 작성

private static RequestMatcher createDefaultRequestMatcher(String authorizationEndpointUri) {
    /**
     *  GET /oauth2/authorize
     * 	OAuth 인가 요청의 기본 형태 (RFC 6749 3.1)
     * 	POST도 가능
     */
    RequestMatcher authorizationRequestGetMatcher = PathPatternRequestMatcher.withDefaults()
            .matcher(HttpMethod.GET, authorizationEndpointUri);
    RequestMatcher authorizationRequestPostMatcher = PathPatternRequestMatcher.withDefaults()
            .matcher(HttpMethod.POST, authorizationEndpointUri);

    /**
     * 인가 요청 판별
     * 다음 중 하나면 Authorization Request
     * 	1. GET /oauth2/authorize
     * 	2. POST /oauth2/authorize AND response_type 있음
     */
    RequestMatcher authorizationRequestMatcher = new OrRequestMatcher(authorizationRequestGetMatcher,
            new AndRequestMatcher(authorizationRequestPostMatcher));

    /**
     *  이 Filter는 최초 인가 요청
     */
    return new OrRequestMatcher(authorizationRequestMatcher);
}

 

/oauth2/authorize 검사

이는 브라우저 → 인가 서버 즉, 사용자가 로그인 버튼을 누르고 브라우저가 인가 서버에게 요청을 보낸 상황임.

GET /oauth2/authorize?response_type=code&client_id=...

 

  • 여기서부터 OAuth2AuthorizationEndpointFilter가 동작 시작하며
  • 밑 코드가 진입점이다.
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

 

모든 HTTP 요청은 이 Filter로 들어온다.

@Override
protected void doFilterInternal(
    HttpServletRequest request,
    HttpServletResponse response,
    FilterChain filterChain
)

 

  • 밑 코드가 가로채게 됨 /oauth2/authorize가 아니면 → 다음 필터로 넘김
if (!authorizationEndpointMatcher.matches(request)) {
    filterChain.doFilter(request, response);
    return;
}

 

  • 밑 메소드는 요청의 경로가 /oauth2/authorize 인지, HTTP 메소드가 허용되는지 OAuth 파라미터 조건을 만족하는지를 검사함.
matches

즉, createDefaultRequestMatcher를 탄다.

 

 

URL 검사 && HTTP Method 검사

  • 밑 코드에서 PathPatternRequestMatcher가 진행함 URL 검사 또한 HTTP 메소드까지 검사
  • HttpServletRequest에서
    • HTTP Method (GET / POST)
    • Request Path (/oauth2/authorize)

를 꺼내서

요청의 path == "/oauth2/authorize" 인가?
요청의 method == GET 인가?

를 직접 비교

RequestMatcher authorizationRequestGetMatcher = PathPatternRequestMatcher.withDefaults()
        .matcher(HttpMethod.GET, authorizationEndpointUri);
RequestMatcher authorizationRequestPostMatcher = PathPatternRequestMatcher.withDefaults()
        .matcher(HttpMethod.POST, authorizationEndpointUri);

 

 

URL 주입

private static final String DEFAULT_AUTHORIZATION_ENDPOINT_URI = "/oauth2/authorize";

public OAuth2AuthorizationEndpointFilter() {
	this(DEFAULT_AUTHORIZATION_ENDPOINT_URI);
}

public OAuth2AuthorizationEndpointFilter(String authorizationEndpointUri) {
    Assert.hasText(authorizationEndpointUri, "authorizationEndpointUri cannot be empty");
    /**
     * 어떤 HTTP 요청을 /oauth2/authorize 인가 요청으로 볼 것인가?를 정의하는 요청 판별기(RequestMatcher) 즉, 이 Filter 언제
     * 동작해야하는지 결정하는 규칙
     */
    this.authorizationEndpointMatcher = createDefaultRequestMatcher(authorizationEndpointUri);
}

 

  1. 기본 생성자 == 생성자 체이닝
  • 인가 엔드 포인트 URL을 따로 안 주면 기본 값 /oauth2/authorize를 쓰겠다.
public OAuth2AuthorizationEndpointFilter(AuthenticationManager authenticationManager) {
    this(authenticationManager, DEFAULT_AUTHORIZATION_ENDPOINT_URI);
}

 

 

2. 실제 핵심 생성자 == 생성자 체이닝

public OAuth2AuthorizationEndpointFilter(String authorizationEndpointUri) {
    Assert.hasText(authorizationEndpointUri, "authorizationEndpointUri cannot be empty");
    /**
     * 어떤 HTTP 요청을 /oauth2/authorize 인가 요청으로 볼 것인가?를 정의하는 요청 판별기(RequestMatcher) 즉, 이 Filter 언제
     * 동작해야하는지 결정하는 규칙
     */
    this.authorizationEndpointMatcher = createDefaultRequestMatcher(authorizationEndpointUri);
}

 

 

authorizationEndpointUri == "/oauth2/authorize"

이 값이 그대로 들어가서

PathPatternRequestMatcher.withDefaults()
    .matcher(HttpMethod.GET, authorizationEndpointUri);

 

 

결과

  • 다음과 같이 진행
<http://localhost:8080/oauth2/authorize?client_id=test-client>

 

 

  • 로그인 페이지에서 비번/아이디 입력 후
2026-02-04T19:00:15.140+09:00  INFO 57683 --- [auth-server] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2026-02-04T19:00:15.141+09:00  INFO 57683 --- [auth-server] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
[AuthzFilter] matched: GET /oauth2/authorize?client_id=test-client
[AuthzFilter] matched: GET /oauth2/authorize?client_id=test-client&continue

 

https://github.com/whitecy01/oauth2-authorization-server/commits/main/