쿠키의 전달 방법과 옵션

이창근·2023년 10월 1일
0

Spring공부

목록 보기
7/9

Spring 공부를 하다보니 인증/인가에 관련해서 쿠키를 만들 일이 생기게 되었다. 쿠키의 개념만 어렴풋이 알고 있었어서, 자세한 전달 방식과 여러 옵션들에 대해 정리하며 글을 작성한다.

AuthController.java

@PostMapping("/login")
public ResponseEntity<Object> login(@RequestBody LoginRequest request) {
        
	String accessToken = authService.signin(request);

	ResponseCookie cookie = ResponseCookie
		.from("SESSION", accessToken)
	    .domain("localhost")
	    .path("/")
	    .httpOnly(true)
	    .secure(false)
 	   .maxAge(Duration.ofDays(30))
 	   .sameSite("Strict")
	    .build();

	return ResponseEntity
		.ok()
	    .header(HttpHeaders.SET_COOKIE, cookie.toString())
	    .build();
}

먼저 쿠키를 생성하는 부분이다.
사용자 정보를 RequestBody로 받으면, 서비스계층을 통해 실제 존재하는 사용자인지 확인 후, accessToken값을 발급한다.
이 accessToken값을 레포지토리에 저장하고, 동시에 사용자에게 쿠키로 전달해주면 나중에 인증이 필요한 페이지에 접속할 때 체크를 할 수 있게 되는 것이다.

가장 중요하게 봐야하는 부분은,

ResponseCookie cookie = ResponseCookie
                .from("SESSION", accessToken)
                .domain("localhost")
                .path("/")
                .httpOnly(true)
                .secure(false)
                .maxAge(Duration.ofDays(30))
                .sameSite("Strict")
                .build();

이 부분이다. ResponseCookie라는 Spring 클래스를 통해 쿠키를 만드는데, 각 부분에 대해서 설명을 해보자면,

  • from : 쿠키이름과 쿠키값을 지정한다.
  • domain : 특정 도메인에서만 사용되도록 제한한다.
  • path : 특정 서블릿에만 쿠키를 전달한다.
  • httpOnly : 클라이언트 등을 통해 쿠키가 탈취되는 것을 방지한다. 즉, 브라우저에서 쿠키에 접근하는 것을 막는다.
  • secure : https 요청으로만 쿠키를 주고받을 수 있게 만든다. 쿠키가 탈취 당하더라도 암호화가 되어있으므로 안전하다.
  • maxAge : 쿠키의 만료기간을 설정한다.
  • sameSite : 서드파티요청에 쿠키를 전달할지 설정한다. CSRF 관련 문제를 해결한다.

다음으로 이렇게 생성한 쿠키를 통해 인증/인가를 받을 수 있는 방법을 정리해보았다.

AuthController.java

@GetMapping("/test")
public Long test(UserSession userSession) {
	// 처리하고자 하는 내용
}

AuthResolver.java

@RequiredArgsConstructor
public class AuthResolver implements HandlerMethodArgumentResolver {

    private final SessionRepository sessionRepository;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(UserSession.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        if (servletRequest == null) {
            throw new Unauthorized();
        }
        Cookie[] cookies = servletRequest.getCookies();

        if (cookies == null || cookies.length == 0) {
            throw new Unauthorized();
        }

        String accessToken = cookies[0].getValue();

        Session session = sessionRepository.findByAccessToken(accessToken)
                .orElseThrow(Unauthorized::new);

        return new UserSession(session.getUsers().getId());
    }
}

WebMvcConfig.java

@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {

    private final SessionRepository sessionRepository;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new AuthResolver(sessionRepository));
    }
}

AuthResolver가 핵심인데, HandlerMethodArgumentResolver를 구현하고, supportsParameter()와 resolveArgument()를 오버라이딩해야한다.

  • supportsParameter() : 어떤 메서드가 ArgumentResolver를 통하게 할 것인지 설정한다. 위 예제에서는 UserSession이라는 파라미터를 받아야만 진행한다.
  • resolveArgument() : 위의 메서드를 통과하면 진행된다. NativeWebRequest를 통해 요청의 여러 정보들을 받아올 수 있고, 위 예제에서는 쿠키를 받아와 인증토큰값을 꺼낸다. 인증토큰값이 레포지토리에 저장된 값이면 통과시킨다.

위와 같은 방식으로 간단하게 토큰을 이용한 인증을 구현할 수 있다. 즉, 로그인 메서드 등에서 토큰을 발급하고, 인증이 필요한 메서드에 대해서는 ArgumentResolver를 통하게 하는 것이다. 더 공부해서 jwt나 SpringSecurity에 관한 내용도 적어보겠다.

profile
나중에 또 모를 것들 모음

0개의 댓글