JWT token 주고받기(로그인)

재운·2021년 4월 10일
2
post-thumbnail

JWT 토큰을 프론트와 주고받은 후기를 토대로 쓰는 내용이다.

1) 준비단계

❗️ 준비물

  • 회원가입 및 로그인 API(django에서는 유저정보 관련 app의 Views.py)
  • request 보내줄(+ response를 받아줄) 프론트 엔드

확인사항

  • 프론트에서 접속할 url
  • HTTP 메소드(GET, POST)
  • 프론트와 key값 조율하기(token, 로그인 성공 메시지 등)

2) JWT 주고받기

1️⃣ 프론트에서 어떤 값들을 넣어줄지, 백엔드에서 어떤 정보들을 처리해줄지 사줄지 의견을 맞춰야한다. 예를들어, 프론트에서 email만 넣을수 있는 상황이고 백엔드 api에는 email, 전화번호 정보를 요구하면 프론트에서 하드코딩으로 전화번호 정보를 넣어주거나, 백엔드에서 전화번호 정보를 넣어주지 않아도 되는 코드를 만들어야한다.

2️⃣ 프론트에서 회원가입 request를 보내고 DB에 회원정보가 제대로 입력되었는지 확인. 내 경우 프론트에서 ID와 PW이 반대로 입력되게 코드가 구현되어 있어서 DB에 거꾸로 들어가게 되었는데, 로그인이 되지않아 한참을 헤매다 DB를 확인해보고 알았다.. 👉 DB 확인 필수!!

3️⃣ DB에 회원정보 제대로 입력된 정보 확인되었으면 로그인 시도

4️⃣ 로그인 성공시 response에 access토큰이 제대로 전달되었는지 확인

5️⃣ 웹 브라우저의 local storage에 토큰이 저장되어있는지 확인

6️⃣ 프론트에서 토큰을 받고 다시 정보를 백엔드에 요청을 하게되면 HTTP request header에 토큰을 담게 되는데, 이때 토큰이 담긴 키값을 서로 확인해야된다.(일반적으로는 'Authorization'이라느 키에 담긴다.)

7️⃣ 백엔드에서 토큰을 받으면 이를 복호화해서 DB에 있는 사용자인지 확인하는 작업을 진행한다.


def login_check(func):
    def wrapper(self,request,*args, **kwargs):
        try:
            
            access_token = request.headers.get('Authorization', None)
            unhashed = jwt.decode(access_token, SECRET, algorithms='HS256')
            if User.objects.filter(username=unhashed['username']).exists():
                request.user = User.objects.filter(username=unhashed['username'])
                return func(self, request, *args, **kwargs)
        
            return JsonResponse({'message':"UNAUTHORIZED_USER"}, status=400)
        
        except jwt.exceptions.DecodeError:
            return JsonResponse({'message' : 'INVALID_TOKEN'}, status=400)

        except KeyError:
            return JsonResponse({'message' : 'No_TOKEN' }, status=400)
        
    return wrapper

❗️ 주의할점
☑️ jwt.decode(access_token, SECRET, algorithms='HS256')
이 부분에서 'algorithms' 처럼 algorithm뒤에 's' 를 붙여야 된다. s가 없어서 디코딩 에러 원인을 확인하는데 상당히 애를 먹었다..ㅠ
웃긴건 로그인 후 토큰 생성시 사용되는 인코딩 코드에는 alogorithm(s가 안붙는다.) 이라고 쓴다.
👉 이부분은 JWT 공식 문서에도 기재되어있다. 왜그런거지..😂

☑️ request.user
로그인 후 닉네임을 가지고 댓글을 달거나 사진을 업로드하는 등의 행위는 request의 body에 사용자 정보가 담겨있지 않는 이상 토큰을 복호화하여 얻은 사용자 정보를 사용해야되는데,
토큰을 복호화하는 데코레이터 안에서 사용자의 정보에 해당하는 객체를 저장하려면 request(ex: request.user) 안에 또다른 인스턴스를 만들어서 저장해야된다.
(이렇게 하지 않고 그냥 user = 객체 이런식으로 저장하면 데코레이터 함수 안에서만 적용되는 변수여서 밑의 GET,POST 함수를 실행할때 불러올 수 없다.)

profile
Life is memory

0개의 댓글