의문

그런데 API 하나하나 만들때 마다 인증이 필요한 부분에 검증 로직을 넣어야하는가?

전에도 언급했듯 3번 이상 반복되는 행위는 내가 뭔가 잘못하고있는게 아닌가? 하는 의문을 가져야한다.

그런 일들은 대개 해결방법이 있고, 없는 경우 설계가 잘못됐는지 의심을 해봐야한다.

 


인터셉터

이런 반복되는 작업인 공통관심사를 인터셉터를 이용해 해결해볼것이다.

인터셉터에 관해서는 여기에 정리해두었다.

이전 게시글에서 했던 작업들은 원래대로 롤백하고 진행한다.

 

PostController

간단하게 Get 요청 시 Hello World 를 반환하는 컨트롤러를 만든다.

@GetMapping("/hello")
public String hello() {
    return "Hello World";
}

 

AuthInterceptor

요청 헤더의 accessToken 에 "midcon" 이라는 값이 담겼는지 확인하는 인증 로직을 수행하는 인터셉터를 만든다.

@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info(">> preHandle");
        String accessToken = request.getHeader("accessToken");
        if (accessToken != null && accessToken.equals("midcon")) {
            return true;
        }
        throw new UnauthorizedException();
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info(">> postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info(">> afterCompletion");
    }
}

 

UnauthorizedException

인증 실패시 발생하는 커스텀 예외

public class UnauthorizedException extends DunpleException{

    private static final String MESSAGE = "인증이 필요합니다.";

    public UnauthorizedException() {
        super(MESSAGE);
    }

    @Override
    public int getStatusCode() {
        return HttpStatus.UNAUTHORIZED.value();
    }
}

 

WebMvcConfig

인터셉터를 적용하기 위해 WebMvcConfig 를 설정한다.

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor());
    }
}

 

PostControllerTest

accessToken 이라는 헤더에 "midcon" 이라는 값을 넣어서 Get 요청을 보낸다.

@DisplayName("/hello 요청시 Hello World 를 출력한다.")
@Test
void hello() throws Exception {
    mockMvc.perform(
        MockMvcRequestBuilders.get("/hello")
            .header("accessToken","midcon")
        )
        .andExpect(status().isOk())
        .andExpect(content().string("Hello World"))
        .andDo(print());
}

 

의도한대로 accessToken 헤더에 "midcon" 을 넣어주면 테스트는 성공하고 

아래처럼 잘못된 값을 넣거나 아예 넣지 않으면 401 에러가 뜨면서 실패한다.

 

 


특정 페이지는 인증을 넣고 다른건 넣기 싫다면?

지금까지 한 방식대로는 모든 페이지에서 인증과정을 거쳐야한다.

하지만 우리의 서비스는 충분히 인증이 필요한 페이지가 있고 필요없는 페이지가 있을 수 있다.

특정 URL 의 요청에만 인터셉터를 적용하거나 특정 URL 만 적용하지 않을 수는 없을까?

 

WebMvcConfig

WebMvcConfig 에 적용할 URL 을 넣거나 적용하지 않을 수 있다.

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new AuthInterceptor())
        .excludePathPatterns("/hello")
        .addPathPatterns("/posts");
}

ㄴ excludePathPatterns

입력한 URL 패턴에선 인터셉터를 적용하지 않는다.

ㄴ addPathPatterns

입력한 URL 패턴에선 인터셉터를 적용한다.

+ Recent posts