Cookie에 JWT 담아 Security 인증하기

Sol's·2023년 1월 30일
0

팀프로젝트

목록 보기
6/25

앞서 개인프로젝트에서 Session에 JWT를 담아 로그인을 진행했습니다.

Jwt는 Session에 담을 수도있지만, Cookie에도 담을 수 있어 팀프로젝트에는 Cookie에 담아서 Jwt를 시큐리티 컨텍스트 홀더에 담고 싶었습니다.

팀 회의를 통해 Session보다 Cookie가 더 효율적이라는 판단에 Cookie에 담기로 하였고 저는 OAuth로그인을 담당하였기 때문에 자연스럽게 Cookie를 통해 로그인 처리를 하게 되었습니다.

Cookie에는 특수문자가 포함될수 없다.

Jwt를 쿠키에 담아서 보내겠다고 쿠키를 설정하는방법을 검색해서 알아보고 실행해 보았더니 에러를 만났습니다.
워낙 에러를 자주만나 놀랍지도 않았지만 쿠키 설정은 어려울게 없어 왜 에러가 발생했는지 궁금했습니다.

character 32면 스페이스일텐데?? 라는 생각에 쿠키의 값설정에 대해 검색을 해보았습니다.

쿠키 값에는 공백, 괄호, 등호, 콤마, 콜론, 세미콜론을 포함할 수 없으며 이들 값을 포함하려면
인코딩이 필요합니다.

방법은 있었습니다.
쿠키를 설정할때 URLEncoder.encode(cookieValue, "UTF-8")을하고
쿠키를 가져올때 URLDecoder.decode(cookieValue, "UTF-8")하면 됩니다.

JWT의 구조를 파악하지 못해 발생한 에러

하지만 쿠키를 설정하고 가져올때 귀찮아 질거라는 판단을 하였고
쿠키를 설정할때는 임의의 특수문자(Bearer.)를 주고, Security Filter에서는 repolace를 통해 받아야 겠다고 생각했습니다.

  • Controller에서의 Cookie설정
@PostMapping("/view/v1/signin")
    public String login(UserLoginRequest userLoginRequest, HttpServletResponse response) throws UnsupportedEncodingException {

        UserLoginResponse tokens = userService.login(userLoginRequest);

        //cookie 설정은 스페이스가 안되기 때문에 Bearer 앞에 .를 붙인다. Security Filter에서 . -> " " 로 치환할 것이다.
        Cookie cookie = new Cookie("jwt", "Bearer."+tokens.getAccessToken());
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
        return "redirect:/view/v1/crews";
    }
  • Security Filter에서 Cookie 받아오기
if (token == null) {
            Cookie[] cookies = request.getCookies();
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals("jwt")) {
                    token = cookie.getValue().replace(".", " ");
                    log.info("cookie token = {}", token);
                }
            }
        }

이번에도 예상치 못한 오류가 발생했습니다.

오류를 자세희 들여다보니 Jwt검증하는 로직에서 예외가 발생했고 디버깅을 해보았습니다.

이번에는 JWT의 구성에대해 잘 몰라 생긴 오류였습니다.
결론부터 말하자면 .을 replace해서 발생한 오류입니다.
JWT는 .을 구분자로 Header.payload.signature의 구성으로 되어있기 때문입니다.

오류 해결

JWT의 구분자 . 대신 +를 사용해 해결했습니다.

  • Controller
@PostMapping("/view/v1/signin")
    public String login(UserLoginRequest userLoginRequest, HttpServletResponse response) throws UnsupportedEncodingException {

        UserLoginResponse tokens = userService.login(userLoginRequest);

        //cookie 설정은 스페이스가 안되기 때문에 Bearer 앞에 +를 붙인다. Security Filter에서 + -> " " 로 치환할 것이다.
        Cookie cookie = new Cookie("jwt", "Bearer+"+tokens.getAccessToken());
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
        return "redirect:/view/v1/crews";
    }
  • Security Filter
//쿠키 값 셋팅
        if (token == null) {
            Cookie[] cookies = request.getCookies();
            for (Cookie cookie : cookies) if(cookie.getName().equals("jwt")) token = cookie.getValue().replace("+", " ");
        }

Filter에서 Cookie를 받는 로직을 조금 다듬어서 작성하였습니다.

느낀점

Cookie에 Jwt를 담아 로그인 처리를 하면서 Security Filter에대해 더 잘알게되었고 Cookie를 설정하는 방법과
Jwt의 구조와 의미에 대해 더 잘알게되었습니다.

그 과정에서 에러를 만나 해결을하면서 알고리즘공부를 했던 경험이 있기에 좀 더 다양한 방법으로 해결을 할 수 있었다고 느꼈습니다.
앞으로 개발을 공부하면서 지금처럼 알고리즘 공부도 꾸준히 해야겠습니다:)

profile
배우고, 생각하고, 행동해라

0개의 댓글