몇 분 만에 React Django 앱용 JWT 설정

20999 단어 djangojwtreact
이전 게시물에서 JWT가 무엇인지 설명했습니다.

오늘은 React 프론트엔드와 Django 백엔드가 있는 프로젝트에서 어떻게 사용하는지 보여드리겠습니다.

Django의 백엔드 부분



Python, Django 및 Django Rest Framework에 대한 기본 지식이 이미 있는 것 같습니다.

pip로 필요한 패키지를 설치합니다.

pip install djangorestframework-simplejwt


이제 settings.py 파일로 이동하여 패키지를 설정합니다.

REST_FRAMEWORK = {
    # ... others DRF setup
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework_simplejwt.authentication.JWTAuthentication"
    ],
}

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=1),
}


이제 설정에 대한 설명입니다. 인증을 위해 simplejwt를 기본값으로 사용하도록 Django Rest Framework를 설정했습니다.

Simplejwt는 사용자당 2개의 토큰을 제공합니다.
  • 리소스에 직접 액세스하려면 액세스 토큰이 필요합니다. 그들은 일반적으로 만료 날짜가 있고 수명이 짧습니다. 여기서는 5분 후에 만료되도록 설정했습니다.
  • 새 액세스 토큰을 얻으려면 새로 고침 토큰이 필요합니다. 액세스 토큰이 만료되면 사용자는 새로 고침 토큰으로 인증 서버에 요청하여 새로운 액세스 토큰을 얻습니다. 새로 고침 토큰도 만료될 수 있지만 수명이 깁니다. 1일 후에 만료되도록 설정했습니다.

  • Django의 마지막 부분은 사용자가 토큰을 얻을 수 있는 경로입니다.

    from django.urls import path
    
    from rest_framework_simplejwt.views import (
        TokenObtainPairView,
        TokenRefreshView,
    )
    
    urlpatterns = [
        path("token/", TokenObtainPairView.as_view(), name="obtain_token"),
        path("token/refresh/", TokenRefreshView.as_view(), name="refresh_token"),
    ]
    


    첫 번째는 비밀번호와 사용자 이름을 사용하여 사용자 인증에 대한 경로 가져오기 토큰입니다.

    두 번째는 새로 고침 토큰이 필요하며 새로운 액세스 토큰을 돌려줍니다.

    React를 사용한 프론트엔드 부분



    Javascript 및 React에 대한 기본 지식이 이미 있는 것 같습니다.

    먼저 원하는 패키지 관리자를 사용하여 필요한 패키지를 설치합니다.

    yarn add jsonwebtoken
    # or
    npm install jsonwebtoken
    


    JWT를 관리하려면 React와 함께 2개의 서비스가 필요합니다.

    서비스 요청



    Axios를 사용하지만 가져오기에서도 작동합니다.

    import axios from "axios";
    
    import { useDispatch } from "react-redux";
    
    import { TokenService } from "..";
    
    import { deleteUserData } from "../../../Accounts/actions";
    
    const requestService = axios.create({
      baseURL: process.env.REACT_APP_API_ENTRYPOINT,
    });
    
    requestService.interceptors.request.use(
      (config) => {
        const token = TokenService.getAccessToken();
        if (token) {
          // eslint-disable-next-line no-param-reassign
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => {
        Promise.reject(error);
      },
    );
    
    requestService.interceptors.response.use(
      (response) => response,
      (error) => {
        const originalRequest = error.config;
        const valid = TokenService.getRefreshTokenValidity();
        // if refresh token is expired, redirect user to login with action
        if (!valid) {
          useDispatch(deleteUserData());
        }
    
        if (error.response.status === 401 && !originalRequest.retry) {
          originalRequest.retry = true;
          return requestService({
            url: "/api/v1/accounts/token/refresh/",
            method: "post",
            data: {
              refresh: TokenService.getRefreshToken(),
            },
          }).then((res) => {
            if (res.status === 200) {
              TokenService.setToken(res.data);
    
              requestService.defaults.headers.common.Authorization = `Bearer ${TokenService.getAccessToken()}`;
    
              return requestService(originalRequest);
            }
            return null;
          });
        }
        return Promise.reject(error);
      },
    );
    
    export default requestService;
    


    먼저 Axios 인스턴스를 만듭니다.

    2개의 인터셉터를 생성한 후:
  • 요청의 경우: 모든 요청에 ​​액세스 토큰을 추가합니다.
  • 응답: 액세스 토큰이 만료된 경우 새 토큰을 얻기 위해 새로 요청합니다. 그런 다음 새 토큰으로 원래 요청을 재생합니다. 또 다른 경우는 갱신 토큰이 만료된 경우입니다. 그 때 우리는 사용자 데이터를 제거하고 로그인 페이지로 리디렉션합니다.

  • 토큰 서비스



    두 번째 서비스는 토큰을 관리하는 것입니다.

    우리는 로컬 스토리지로 토큰을 관리하고 서비스는 토큰을 설정, 가져오기, 유효성 확인 또는 삭제할 수 있습니다.

    한 가지 주의하세요. 갱신 토큰을 사용하면 악의적인 사람이 사용자인 것처럼 가장할 수 있습니다. 로컬 저장소에 장기 토큰을 저장하는 것은 좋지 않습니다.

    import jwt from 'jsonwebtoken';
    
    const TokenService = (function tokenService() {
      let service;
      function getServiceFunc() {
        if (!service) {
          service = this;
          return service;
        }
        return service;
      }
    
      const setToken = (tokenObj) => {
        if (tokenObj.access) {
          localStorage.setItem('accessToken', tokenObj.access);
        }
        if (tokenObj.refresh) {
          localStorage.setItem('refreshToken', tokenObj.refresh);
        }
      };
    
      const getAccessToken = () => localStorage.getItem('accessToken');
    
      const getRefreshToken = () => localStorage.getItem('refreshToken');
    
      const getTokenValidity = (tokenObj) => {
        const decodedToken = jwt.decode(tokenObj, { complete: true });
        const dateNow = new Date();
        const timeStamp = dateNow.getTime() / 1000;
    
        if (decodedToken.payload.exp < timeStamp) {
          return false;
        }
        return true;
      };
    
      const getAccessTokenValidity = () => {
        const accessToken = getAccessToken();
        if (accessToken) {
          return getTokenValidity(accessToken);
        }
        return null;
      };
    
      const getRefreshTokenValidity = () => {
        const refreshToken = getRefreshToken();
        if (refreshToken) {
          return getTokenValidity(refreshToken);
        }
        return null;
      };
    
      const clearToken = () => {
        localStorage.removeItem('accessToken');
        localStorage.removeItem('refreshToken');
      };
    
      return {
        getService: getServiceFunc,
        setToken,
        getAccessToken,
        getRefreshToken,
        getAccessTokenValidity,
        getRefreshTokenValidity,
        clearToken,
      };
    }());
    
    export default TokenService;
    
    


    결론



    이것이 React 프런트엔드와 Django 백엔드 사이에 간단한 JWT 인증을 설정하는 데 필요한 전부입니다.

    JWT는 앱 간의 인증을 관리하는 훌륭한 솔루션입니다.

    자원 :
  • Django
  • Django Rest Framework
  • Django Rest Framework Simple JWT
  • React
  • Axios
  • jsonwebtoken
  • 좋은 웹페이지 즐겨찾기