버글버글

[React] localStorage에 token 저장하기 (feat.JWT) 본문

React/react 공부기록

[React] localStorage에 token 저장하기 (feat.JWT)

Bugle 2023. 4. 12. 16:00
반응형

localStorage란?

 

- 웹 브라우저에서 제공하는 웹 스토리지(Web Storage) 중 하나로, 키-값 쌍(key-value pairs)을 저장할 수 있는 클라이언트 사이드 저장소이다.
- localStorage에 저장된 데이터는 브라우저를 닫아도 유지되며, 같은 도메인에서 실행되는 페이지들은 동일한 localStorage에 접근할 수 있다.
- 주로 사용자의 기본 설정, 로그인 정보, 쇼핑 카트 등을 저장하는 데에 이용된다.

 

localStorage 명령어

 

    localStorage.setItem("key 이름", value)     localStorage 추가하기
    localStorage.getItem("key 이름")     localStorage 값 가져오기
    localStorage.removeItem("key 이름")     localStorage 값 지우기

 

localStorage 어디에 저장되었는지 확인하기

 

1. [F12]로 개발자 도구를 연다.

2. [Application]을 클릭한다.

3. [Local Storage]를 클릭한다.

4. url을 클릭하면 key, Value값이 나온다.

값이 들어가기 전
값이 들어간 경우

 

localStorage에 jwt 저장하기

 

▶ jwt? 

- JWT(JSON Web Token)는 웹 애플리케이션에서 인증 정보를 안전하게 전달하기 위한 방식 중 하나이다.
- JSON 포맷으로 인코딩된 토큰을 사용하여 정보를 전달하며, 서버와 클라이언트 간에 안전하게 인증 정보를 전달할 수 있다.
- 헤더, 페이로드, 서명(signature) 세 부분으로 이루어져 있다.

  (1) 헤더 = 토큰의 타입과 사용하는 해시 알고리즘 등의 정보가 포함

  (2) 페이로드 = 클라이언트가 요청할 때 함께 전달하려는 정보(예: 사용자 ID)가 포함

  (3) 서명 = 헤더와 페이로드를 기반으로 생성된 서명값으로, 토큰이 유효한지 검증할 때 사용
- JWT를 사용하면 클라이언트와 서버 간의 세션 상태를 유지할 필요 없이, 각 요청에서 인증 정보를 전달하여 사용자를 인증할 수 있음.

- 여러 서버 간에 인증 정보를 공유할 수 있어서 분산환경에서도 유용하게 사용됨

 

▶ token? 

- 인증정보를 안전하게 전단하기 위한 문자열이다.

- HTTP는 단기기억상실과 같은 stateless 특성을 가지고 있기 때문에 한 번 로그인을 한다고 그 사실을 계속 기억하지 못하기 때문에, 로그인을 했더라도 마이페이지 등 로그인이 필요한 사이트에 접속할 때마다 로그인을 진행해야 한다. 이러한 상황을 막기위해 token을 사용 한다.

- 로그인을 완료하면 token이 발급(?) 되고 마이페이지 등 로그인이 필요한 페이지로 이동 할 때마다 서버에 token을 보내 권한이 있다고 알려주기 때문에 다시 로그인 할 필요가 없다.

 

1. axios로 로그인 성공시, "key 이름"에 value(값) 넣어주기

  const handleLogin = () => {
      axios.post('/auth/login', {
        userId: userId,
        userPw: userPw,
      })
      .then(function(obj) {
        localStorage.setItem("key 이름", "value");
        const config = {
          headers: {
            Authorization: `${localStorage.getItem("key 이름")}`,
          },
        };
        axios.get('/try', config)
          .then(function (response) {
            console.log("refresh_token 값 : " + response.data); // 콘솔에 value가 찍힘
            alert(userId + "님 환영합니다.");
          })
          .catch(function (error) {
            console.log("오류 " + error);
          });
        })
      .catch(() => {
        alert("아이디 또는 비밀번호를 잘못 입력했습니다. 입력하신 내용을 다시 확인해주세요.")
      })
    
  };

 

2. 다른 페이지로 넘어갈때 token 확인하고 페이지 이동하기

const config = {
  headers: {
    Authorization: `${localStorage.getItem("refresh_token")}`,
    // localStorage에 token이 저장되어 있는지 확인하기
  },
};

axios.get('/try', config)
.then(function() { // 성공
  // 원하는 페이지 이동 (예를 들면 마이페이지 등)
    window.location.href = "/mypage";
})
.catch(function() { // 실패
  // 원하는 페이지 이동 (예를 들면 로그인페이지 등)
  window.location.href = "/login";
})

 

■ 최종 코드

더보기
import React, { useEffect, useState } from 'react';
import axios from 'axios';

// mui
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Box from '@mui/material/Box';
import theme from "./api/theme";
import styled, { ThemeProvider } from "styled-components";
import { InputAdornment, Checkbox, FormControlLabel  } from '@mui/material';

function Login() {

  const [userId, setUserId] = useState('');
  const [userPw, setUserPw] = useState('');

  const handleLogin = () => {
    if(userId === "") {
      alert("아이디를 입력해주세요.");
    } else if (userPw === "") {
      alert("비밀번호를 입력해주세요.")
    } else {
      axios.post('/auth/login', {
        userId: userId,
        userPw: userPw,
      })
      .then(function(obj) {
        localStorage.setItem("refresh_token", obj.data.data.authToken);
        const config = {
          headers: {
            Authorization: `${localStorage.getItem("refresh_token")}`,
          },
        };
        axios.get('/try', config)
          .then(function (response) {
            console.log("refresh_token 값 : " + response.data);
            alert(userId + "님 환영합니다.");
            window.location.href = "/";
          })
          .catch(function (error) {
            console.log("오류 " + error);
          });
        })
      .catch(() => {
        alert("아이디 또는 비밀번호를 잘못 입력했습니다. 입력하신 내용을 다시 확인해주세요.")
      })
    }
  };

  return (

    <Box>
      <ThemeProvider theme={theme}>
        <form>
          <TextField
            type="text"
            label="아이디"
            margin="normal"
            value={userId}
            onChange={(e) => setUserId(e.target.value)}
            fullWidth
            variant="standard"
          />
            
          <TextField
            type="password"
            label="패스워드"
            margin="normal"
            value={userPw}
            onChange={(e) => setUserPw(e.target.value)}
            autoComplete="on"
            fullWidth
            variant="standard"
          />
            
          <Button
            onClick={handleLogin}
      	  >로그인</Button>
        </form>
      </ThemeProvider>
    </Box>
    
    );
}

export default Login;

 

 

 

참고블로그

https://dev-bomdong.tistory.com/19

반응형