인프런 커뮤니티 질문&답변

새옹지마님의 프로필 이미지

작성한 질문수

Practical Testing: 실용적인 테스트 가이드

Persistence Layer 테스트 (1)

잘못된 Interceptor 사용으로 인한 h2-console 접근 문제

작성

·

114

·

수정됨

0

안녕하세요. 강의에서 h2 db를 사용하시는 것을 보고 제 개인프로젝트에서 profile이 test일 경우에 h2 db를 써보기로 결정했습니다.

그런데 제가 AuthInterceptor를 잘못 만들어서인지 localhost:8080/h2-console url로 접속하면 JSON 응답이 나와버립니다. 어떤 코드가 잘못되었는지, 어떻게 개선해야 하는지 봐주실 수 있으실까요..? 제가 작성한 코드와 설명을 남깁니다.

스크린샷 2024-08-10 오전 2.02.10.png

 

application.yml

spring:
  profiles:
    default: local

  jpa:
    hibernate:
      ddl-auto: none

  mail:
    host: smtp.gmail.com
    port: 587
    username: kanggi1997@gmail.com
    password: 보안을위해지웁니다
    properties:
      mail:
        smtp:
          starttls:
            enable: true
          auth: true
---
spring:
  config:
    activate:
      on-profile: local

  datasource:
    url: jdbc:postgresql://localhost:5432/forecast?useSSL=false
    driver-class-name: org.postgresql.Driver
    username: gunwoo

  jpa:
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
        format_sql: true

    show-sql: true
    hibernate:
      ddl-auto: update

---
spring:
  config:
    activate:
      on-profile: test
  h2:
    console:
      enabled: true # /h2-console 설정
  datasource:
    url: jdbc:h2:mem:~/databasesByH2/forecastBE
    driver-class-name: org.h2.Driver
    username: sa
    password:

  jpa:
    properties:
      hibernate:
        format_sql: true
    show-sql: true
    hibernate:
      ddl-auto: create

 

spring security를 사용하는데 어려움을 느껴 직접 인가를 구현하기 위해 AuthInterceptor와 WebConfig를 구성했고 사이트 회원만 api에 접근할 수 있게 만들었습니다. 로그인하지 않았을 경우 로그인이 필요하다는 메시지를 JSON형태로 전달합니다.

AuthInterceptor

package site.gunwoo.forecastBE.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import site.gunwoo.forecastBE.dto.ResponseDTO;

@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    private ObjectMapper mapper = new ObjectMapper();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if ("OPTIONS".equals(request.getMethod())) {
            log.debug("preflight은 통과시킴");

            return true;
        }
        String loggedInUserEmail = (String) request.getSession().getAttribute("loggedInUser");
        if (loggedInUserEmail == null) {

            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("UTF-8");
            response.setStatus(HttpStatus.UNAUTHORIZED.value());

            ResponseDTO responseDTO = new ResponseDTO("로그인이 필요합니다.", null);
            String jsonResponse = mapper.writeValueAsString(responseDTO);
            response.getWriter().write(jsonResponse);
            return false;
        }
        return true;
    }
}

 

아래의 addInterceptors 메서드에서 AuthInterceptor의 처리를 거치지 않아도 되는 uri를 정의했습니다. h2 콘솔 접근을 위한 uri인 "/h2-console"도 포함시켰습니다. 하지만 여전히 로그인이 필요하다는 응답이 JSON 형식으로 나타납니다.

WebConfig

package site.gunwoo.forecastBE.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    private final AuthInterceptor authInterceptor;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:5173")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("Authorization", "Content-Type")
                .exposedHeaders("Custom-Header")
                .allowCredentials(true)
                .maxAge(3600);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/join")
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/test")
                .excludePathPatterns("/regions")
                .excludePathPatterns("/h2-console"); //적용이 안되는 듯
    }
}

답변 1

0

박우빈님의 프로필 이미지
박우빈
지식공유자

안녕하세요, 새옹지마 님!

올려주신 내용만 보고 정확한 원인을 파악하기는 어렵지만, 몇 가지 의심해볼 수 있는 포인트들을 남겨보겠습니다.

  • /h2-console/** 과 같이 하위 경로를 포함해서 등록해보면 어떨까요?

    • /user/login, /test, /regions

      과 같은 경로들은 작성자 분께서 직접 만든 API path로 보이는데, h2-console은 그렇지 않다보니 하위 경로들을 전부 등록해주어야 할 것 같습니다.

    • 또한 h2-console에 접근할 때 서버로 어떤 API들을 요청하게 되는지 확인해볼 필요가 있습니다. 웹 개발자도구를 열어 네트워크 탭을 한번 살펴보세요. /h2-console/** 하위 요청들이 다수 나가고 있는 것을 확인할 수 있습니다.

  • 다른 exclude 패턴들은 정상적으로 제외되나요? (/user/login, /test, /regions 등)

     

한번 확인해보시고 말씀 주세요.

감사합니다 🙂