[TIL] React 로그인 (JWT, Local Storage): token 저장, 서버에 전달하기

대빵·2023년 11월 30일
1

token, 필요한이유??

HTTP는 단기기억살실과 같은 stateless 특성을 가지고 있기 때문에 한 번 로그인을 한다고 그 사실을 계속 기억하지 못한다. 원래대로라면 로그인을 했더라도 접속할때마다 로그일을 진행해야 한다. 이러한 상황을 막기 위해 token이 필요하다.
로그인을 완료하면 인증 스티커와 같은 token을 전달받고, 필요한 사이트를 접솔할 때마다 서버에 token을 보내며 로그인을 한 유저인지, 권한이 있는지 알려줘서 다시 로그인을 할 필요가 없다.

JWT(Jason Web Token)란?

사용자 인증(Authentication)을 수행할 때 사용하는 암호화된 토큰이다.
사용자의 정보 등을 암호화하여 사용자 정보가 필요한 API를 호출할 때, 해당 토큰을 보내주면 백엔드에서 그 토큰을 검증하는 과정을 거친다. 그 후 response를 해주는 것이다.

개발자 도구에서 Local Storage를 확인 할 수 있다.

localStorage와 sessionStorage

웹 스토리지 객체(web storage object)인 localStorage와 sessionStorage는 브라우저 내에 키-값 쌍을 저장할 수 있게 해다.

이 둘을 사용하면 페이지를 새로 고침하고(sessionStorage의 경우) 심지어 브라우저를 다시 실행해도(localStorage의 경우) 데이터가 사라지지 않고 남아있습니다.

  • 쿠키와 다르게 웹 스토리지 객체는 네트워크 요청 시 서버로 전송되지 않습니다. 이런 특징 때문에 쿠키보다 더 많은 자료를 보관할 수 있습니다. 대부분의 브라우저가 최소 2MB 혹은 그 이상의 웹 스토리지 객체를 저장할 수 있도록 해줍니다. 또한 개발자는 브라우저 내 웹 스토리지 구성 방식을 설정할 수 있습니다.

  • 쿠키와 또 다른 점은 서버가 HTTP 헤더를 통해 스토리지 객체를 조작할 수 없다는 것입니다. 웹 스토리지 객체 조작은 모두 자바스크립트 내에서 수행됩니다.

  • 웹 스토리지 객체는 도메인·프로토콜·포트로 정의되는 오리진(origin)에 묶여있습니다. 따라서 프로토콜과 서브 도메인이 다르면 데이터에 접근할 수 없습니다.

API

  • setItem(key, value) – 키-값 쌍을 보관
  • getItem(key) – 키에 해당하는 값을 받아오기
  • removeItem(key) – 키와 해당 값을 삭제
  • clear() – 모든 것을 삭제
  • key(index) – 인덱스에 해당하는 키를 받아오기
  • length – 저장된 항목의 개수를 얻기
  • Object.keys를 사용해 키 전체를 얻기
    객체 프로퍼티처럼 키에 접근할 수 있는데, 이 경우 storage 이벤트가 발생하지 않습니다.

storage 이벤트

  • setItem, removeItem, clear를 호출할 때 발생합니다.
  • 연산(key/oldValue/newValue)과 관련된 데이터 전체와 문서 url, 스토리지 객체 storageArea를 가지고 있습니다.
  • 이벤트가 생성된 곳을 제외하고 스토리지에 접근하는 모든 window 객체에서 일어납니다(sessionStorage는 탭 내에서, localStorage에서는 전역에서)

로그인 과정

유저 정보를 저장한 후에 로그인을 할 때 암호화된 비밀번호화 비교하는 검증 과정을 거친 후 일치하게 되면 로그인을 한다.

로그인을 할 때 JWT token을 생성하고 token을 localStorage에 저장하여 로그인을 유지시킨다.

로그아웃을 할 때엔 localStorage에 있는 토큰을 지운다. 

// 토큰을 localStorage에서 삭제
localStorage.removeItem("key");

token을 저장하고 서버에 보내는 방법?

token이 true이면 localStorage에 login-token이라는 키 값으로 token을 저장한다.(localStorage에 저장할 경우 해당 도메인에 영구저장)

try {
      const response = await axios.post(`${process.env.REACT_APP_URL}/login`, userInfo);
  
      if (response.data.accessToken) {
        localStorage.setItem("accessToken", response.data.accessToken);
      }
  
      console.log(response.data);
      navigate("/");
    } catch (error) {
      alert(error.response.data.message);
    }

Authorization가 필요한 사이트에서 token을 전달

  • 'Content-Type': 'application/json': 데이터를 json 형태로 전송
  • Authorization: localStorage.getItem('login-token'): localStorage에 login-token key로 저장한 값을 HTTP Authorization 요청 헤더로 전달
  const userTokenCheck = async () => {
    const response = await axios.get(`${process.env.REACT_APP_URL}/user`, {
      headers: {
        "Content-Type": "application/json", 
        Authorization: localStorage.getItem("accessToken") 
      },
      body: JSON.stringify({})
    });
    console.log(response.data);
  };

0개의 댓글