좌충우돌 개발공부

TIL(20240529) [Spring:AccessToken과 RefreshTocken]


📌 Spring

과제 💡 “회원가입, 로그인 기능이 있는 투두앱 백엔드 서버 만들기”

1) StatusCode 상태코드와 메세지 반환 2) Validation예외처리 검토 3) 10단계까지 도전해보기 4) 과제 마무리 후에 모든 코드 하나씩 주석달면서 해석하기

AccessToken과 RefreshToken

  • AccessToken은 사용자의 정보를 담고 있어서 서비스에 접근할 수 있는 토큰을 의미하는데, JWT는 엑세스 토큰에 해당된다.
  • RefreshToken은 엑세스 토큰이 만료되었을 때 서버에서 확인하여 새로운 AccessToken을 발급해주기 위해 사용한다.

여기서 잠깐! 그럼 쿠키-세션방식 말고 구지 JWT방식을 사용하는가?

🚩 Stateful과 Stateless

💡 stateful: 상태유지로, 세션과 같은 형식을 말하여 클라이언트의 상태를 서버가 저장하고 있다. 쉽게 말해, 사용자가 로그인 한 후에 다른 홈페이지로 갔다가 돌아와도 로그인 상태를 유지하고 있는 것을 의미한다.

💡 stateless: 무상태로 클라이언트의 상태를 보존하고 있지 않는 상태로 서버는 단순히 요청이 오면 응답만 보내는 역할만 수행하게 된다. 즉, 클라이언트와 서버간의 통신에 필요한 모든 상태정보들은 클라이언트에서 가지고 있다가 서버와 통신할 때 데이터를 실어 보내는 구조이다.

🚩 JWT

  • 장점 : 인증을 위한 별도의 저장소가 필요하진 않고, 그로 인해 인증이 빠르며 확장성이 우수하다.
  • 단점 : 담는 데이터의 양이 많아지면 토큰의 길이가 길어져 네트워크의 과부하가 생길 수 있으며, 토큰을 강제로 만료시킬 수가 없어 보안에 취약하다.

    🚩 Cookie와Session

  • 장점 : 서버쪽에서 세션을 통제할 수 있어서 보안측면에서 우수하고 네트워크의 부하가 낮음
  • 단점 : 세션저장소(데이터 용량의 한계)로 인한 서버의 부하가 생길 수 있다.

AccessToken의 한계

1) JWT는 Stateless이기 때문에 서버에서 상태를 관리하지 않는다. 즉, 엑세스 토큰으로 JWT를 사용하여 사용자 검증을 하게 되면 서버에서 토큰의 상태를 제어할 수 없다. 대부분의 웹사이트는 자동 로그아웃이 되는 경우는 잘 없지만, 엑세스 토큰만 사용하는 웹사이트는 토큰이 만료되면 이용중에 자동 로그아웃이 되어 다시 로그인해야하는 상황이 발생한다. 2) 해커에게 토큰을 탈취당한다면 토큰이 만료될 때까진 방법이 없다.

그래서 엑세스의 토큰의 만료시간을 길게 설정한다면 보안상 위험하고, 만료시간을 짧게 설정해도 사용자가 이용중에 자동 로그아웃되는 상황이 발생해 불편을 겪을 것이다.

RefreshToken

  • AccessToken 한계의 해결방법은 아니지만 보완적 측면에서 JWT토큰의 탈취 위험을 최소화 하고, 사용자의 불편을 감소시키기 위해 사용될 수 있으며, 유효기간이 길고 엑세스토큰을 재발급 할 때만 사용된다.
  • 리프레쉬토큰은 엑세스토큰이 만료될 경우 새로운 엑세스토큰을 발급해서 제공한다.
  • 하지만, 그래도 리프레쉬토큰은 탈취위험이 있고 RefreshTokenRotation을 통해 그 위험을 줄일 수 있다.

서버와 클라이언트의 통신은 어떻게 이루어지는가?

1) 로그인 인증에 성공한 클라이언트는 엑세스토큰과 리프레쉬토큰을 갖게되어 로컬에 두 토큰을 저장하게 된다. 2) 헤더에 엑세스토큰을 넣고 API 통신을 한다. 3) 엑세스토큰의 유효시간이 만료될 경우 엑세스토큰은 유효하지 않아 권한이 없는 사용자가 된다. (StatusCode:401응답) 3-1) 엑세스토큰의 갱신이 필요한 경우 헤더에 리프레쉬토큰을 넣고 API를 재요청한다. 4) 리프레쉬토큰으로 사용자의 권한을 확인한 서버는 새로운 엑세스 토큰을 발급한다.


📌 코딩테스트1️⃣ : 수박수박수박수박수박수?

🔒 문제 : 길이가 n이고, “수박수박수박수….”와 같은 패턴을 유지하는 문자열을 리턴하는 함수, solution을 완성하세요. 예를들어 n이 4이면 “수박수박”을 리턴하고 3이라면 “수박수”를 리턴하면 됩니다.

🚫 조건 :

  • n은 길이 10,000이하인 자연수입니다.

🔓 문제풀이

class Solution {
    public String solution(int n) {
        String answer = "";
        for(int i=0; i<n; i++){
            if(i%2 == 0) {
                answer += "수";
            } else {
                answer += "박";
            }
        }
        return answer;
    }
}

🤷‍♀️ 코딩테스트1️⃣ 문제풀이를 하면서 느낀점

: 짝/홀수 어떻게 활용해서 푸느냐의 관점인 듯 했다. 1의 관점에서 수는 홀수, 박은 짝수이지만 0의 관점에서 수는 짝수, 박은 홀수가 된다. 그래서 n이 3이라면 짝(수)/홀(박)/짝(수)이 나와야 하니 i=0을 기준으로 짝/홀/짝이 나올 수 있도록 생각을 해야한다. 아직 실력이 많이 부족한 것 같다. 수학적으로 푸는 연습이 더 필요해 보인다.