- API 인증은 요청이 들어올 때 인증된 요청인가 허용된 사용자인가 확인 후 수행하기 위해서 사용한다.
- Get Parameter 방식
@PostMapping("/posts")
public void post(@RequestBody @Valid PostCreate request, @RequestParam String authorization) {
if(authorization.equals("bis")){
request.validate();
postService.write(request);
}
}
1. RequestParam 방식을 이용하여 쿼리 파라미터로 넘어오는 값을 비교하는 방법이 있다.
- test 코드
//when
mockMvc.perform(MockMvcRequestBuilders.post("/posts?authorization=bis")
.contentType(APPLICATION_JSON)
// .content("{\"title\": \"제목입니다.\", \"content\": \"내용입니다.\"}")
.content(json)
)
.andExpect(status().isOk())
.andDo(print());
1. 테스트 코드를 통해 쿼리 파라미터로 지정된 사용자명이 넘어왔을 때 허용이 된다.
- Header 방식
@PostMapping("/posts")
public void post(@RequestBody @Valid PostCreate request, @RequestHeader String authorization) {
if(authorization.equals("bis")){
request.validate();
postService.write(request);
}
}
1. 쿼리 파라미터가 아닌 요청 속성 중 Header 속성을 사용하는 방법이 있다. @RequestHeader를 이용하는 방식이다.
2. Header의 authorization 속성을 가져와 해당 속성의 값과 비교하여 요청을 인증하는 방식이다.
- test 코드
//when
mockMvc.perform(MockMvcRequestBuilders.post("/posts")
.header("authorization", "bis")
.contentType(APPLICATION_JSON)
// .content("{\"title\": \"제목입니다.\", \"content\": \"내용입니다.\"}")
.content(json)
)
.andExpect(status().isOk())
.andDo(print());
- 테스트 코드에 header 속성 값을 지정하여 테스트를 하게되면 정상적으로 통과하는 것을 볼 수 있다.
- Interceptor
- Spring Interceptor는 웹 애플리케이션에서 HTTP 요청의 처리 과정 중에 특정 작업을 수행하도록 설계된 컴포넌트이다.
1. 인증 및 권한 검사
2. 로깅 및 감사
3. 캐싱
4. 요청 및 응답 변형
5. 예외 처리
- Spring Interceptor는 HandlerInterceptor 인터페이스를 구현하여 작성되며, preHandle, postHandle, afterCompletion과 같은 메서드를 제공하여 요청 처리 전후 및 완료 후에 작업을 수행할 수 있다.
1. preHandle은 핸들러(Controller) 가기전에 무조건 실행된다.
2. postHandle은 핸들러(Controller) 가고 나서 실행된다.
3. afterCompletion은 View로 보낸 이후에 실행된다.
- AuthInterceptor.java
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info(">> preHandle");
}
@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");
}
}
- Interceptor만 작성하게 되면 웹 애플리케이션에 적용되지 않기 때문에 추가적으로 Configuration 코드를 작성해주어야 한다.
- WebMvcConfig.java
package com.islog.api.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
// 여기까지만 사용하면 AuthInterceptor 사용 가능
}
}
1. @Configuration을 이용하여 설정 클래스로 지정하고, WebMvcCOnfigurer를 상속 받는다.
2. addInterceptors 메서드를 이용하여 기존에 생성한 AuthInterceptor 객체를 추가한다.
3. 위 과정을 거쳐야 웹 애플리케이션에 기존에 작성한 AuthInterceptor가 적용된다.
- 디버깅
- 각 log.info를 관찰하기 각 log.info에 포인트를 걸어놓고 디버깅을 해보면
1. url로 요청을 보내게 되면, 아직 응답이 오기전 즉, controller에 도달하기 전 preHandle이 실행된다.
2. 다음 Controller에 요청이 전달되고, 응답이 오고 난 후 postHandle이 실행된다.
3. View까지 전달된 이후 afterCompletion이 실행되는 것을 확인 할 수 있다.
- preHandle의 경우 위에서 확인해본 것과 같이 핸들러에 도달하기 전 실행되는 부분이기 때문에 이전 파라미터, header를 통해 인증을 했던 방식처럼 인증을 사용하게 되면, 모든 controller에 인증이 요청된다.
* preHandle의 반환 타입은 boolean인데, false가 반환되면 핸들러에 정상적으로 도달하지 않는다.
- AuthInterceptor.java
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info(">> preHandle");
String accessToken = request.getParameter("accessToken");
if(accessToken != null && accessToken.equals("bis")){
return true;
}
throw new Unauthorized();
}
1. 요청 파라미터 속성 중 accessToken의 값을 가져와 비교한다.
2. request의 원하는 속성 값이 맞을 경우 return true를 실행하고, 일치하지 않은 경우 예외처리를 한다.
* 추가로 accessToken의 경우 null을 받을 수 있기 때문에 사전에 null에 대한 처리를 해주어야 한다.
- 정상적으로 인증이 완료되었을 때 반환을 하고,
- 인증을 실패하게 되면 예외를 발생시킨다.
- Interceptor 적용 예외
- 모든 요청에 Interceptor를 적용시키지 않고 싶다면 예외를 통해 처리 할 수 있다.
- WebMvcConfig.java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
// 여기까지만 사용하면 그냥 AuthInterceptor 사용 가능
.excludePathPatterns("/test2");
// 인터셉터를 적용 안할 경로를 위와 같이 지정 할 수 있다.
}
}
- .excludePathPatterns를 통해 Interceptor를 예외시키고 싶은 요청 경로를 지정하게 되면 해당 경로는 Interceptor를 적용 받지 않는다.
'Programming > Spring' 카테고리의 다른 글
Spring - API 인증 (http, 고정 인증 로그인 구현) (0) | 2023.10.04 |
---|---|
Spring - API 인증 (ArgumentResolver) (0) | 2023.10.04 |
Spring - 문서화 (Rest Docs 문서) (0) | 2023.09.08 |
Spring - 예외 처리 (0) | 2023.09.06 |
Spring, Java - Builder 패턴 분석 (0) | 2023.09.06 |