DB를 통한 토큰 발급 및 검증 2
이전 게시글이 너무 길어져서 아래에서 이어서 작성한다.
지금까지 공부한 지식을 활용해서 한번 마음대로 인증 로직을 작성할것이다. 인증 과정은 아래와 같다.
- 로그인 성공 시 응답으로 세션 토큰 발급
- 인증이 필요한 페이지에 요청 시 헤더에 담긴 세션 토큰 정보로 DB 에서 확인
2. 인증이 필요한 페이지에 요청 시 헤더에 담긴 세션 토큰 정보로 DB 에서 확인
ArgumentResolver 를 활용해 애노테이션 기반 인증 로직을 만든 것을 활용해보자.
애노테이션 기반 인증 로직 관련은 이 글을 참고하자.
이제 인증이 필요한 페이지에 애노테이션 @Login 을 달아서 구분하고 이 페이지에 접속 시 세션 토큰을 DB를 통해 검증한다.
AuthController
인증이 필요한 페이지에 애노테이션 @Login 을 달아서 구분하고 UserSession 객체에서 이름을 받아 응답값을 반환하는
컨트롤러를 만든다.
@GetMapping("/auth")
public String access(@Login UserSession session) {
return session.getName() + " 님 안녕하세요";
}
AuthResolver
ArgumentResolver를 이용해 애노테이션 @Login으로 인증 로직을 실행할지 말지 구분하고 @Login이 달렸을 경우
Authorization 헤더에 담긴 세션 토큰 정보로 DB에서 사용자 확인작업을 수행한다.
올바른 요청일 시 UserSession 객체에 유저의 이름을 담아 컨트롤러에 보내준다.
@RequiredArgsConstructor
public class AuthResolver implements HandlerMethodArgumentResolver {
private final SessionRepository sessionRepository;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Login.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String accessToken = webRequest.getHeader("Authorization");
if (accessToken == null || accessToken.isBlank()) {
throw new UnauthorizedException();
}
Session session = sessionRepository.findByAccessToken(accessToken)
.orElseThrow(() -> new UnauthorizedException());
return new UserSession(session.getUser().getName());
}
}
UserSession
@Getter
public class UserSession {
private final String name;
public UserSession(String name) {
this.name = name;
}
}
테스트
AuthControllerTest
data.sql 을 통해 초기 유저 데이터가 입력된걸 이용한다.
세션토큰으로 인증이 필요한 페이지에 요청 시 성공 및 실패 케이스를 작성한다.
사실 테스트에서 data.sql 이나 @Transactional 을 사용하는건 바람직하지 않지만 지금은 간단하게 테스트 해보자.
@DisplayName("검증된 세션 값으로 권한이 필요한 페이지에 요청시 접속에 성공한다.")
@Test
@Transactional
void access() throws Exception {
// given
User user = userRepository.findByEmailAndPassword("hyukkind@naver.com", "1234")
.orElseThrow(() -> new InvalidSigninInformationException());
Session session = user.addSession();
// expected
mockMvc.perform(
get("/auth")
.header("Authorization", session.getAccessToken())
.contentType(APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isOk());
}
@DisplayName("검증되지 않은 세션값으로 권한이 필요한 페이지에 요청시 실패한다.")
@Test
@Transactional
void access2() throws Exception {
// given
User user = userRepository.findByEmailAndPassword("hyukkind@naver.com", "1234")
.orElseThrow(() -> new InvalidSigninInformationException());
Session session = user.addSession();
// expected
mockMvc.perform(
get("/auth")
.header("Authorization", 1)
.contentType(APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isUnauthorized());
}
테스트를 수행하면 성공하며 인증 성공 시 UserSession 에 담긴 이름으로 응답이 오는걸 확인할 수 있다.
'API 만들어 보기 > 게시판 API' 카테고리의 다른 글
[API 인증] JWT 를 이용한 인증 1 (0) | 2023.10.07 |
---|---|
[API 인증] 쿠키를 통한 인증 및 검증 (0) | 2023.10.03 |
[API 인증] DB를 통한 토큰 발급 및 검증 1 (0) | 2023.10.01 |
[API 인증] ArgumentResolver 사용해보기 (0) | 2023.09.30 |
[API 인증] Interceptor 사용해보기 (0) | 2023.09.29 |