Flask에서 JWT 사용한 로그인 / 로그아웃 API
1. 로그인 API 만들기
- DB에 저장되어 있는 유저일 때 비밀번호가 일치하면 로그인이 되도록 코드를 작성한다.
- 생성된 토큰으로 처리하는 코드를 작성
1-1. 포스트맨에서 로그인 API 만들기
- 회원가입 정보 입력한다.
1-2. app.py Entry point에 경로 만들기
# 경로(path)와 리소스(API 코드)를 연결한다.
# Entry point
api.add_resource( UserRegisterResource , '/users/login' )
1-3. resources/user.py에 API 코드 작성
import datetime
from email_validator import EmailNotValidError, validate_email
from flask import request
from flask_jwt_extended import create_access_token
from flask_restful import Resource
from mysql.connector import Error
from mysql_connection import get_connection
from utils import check_password, hash_password
class UserLoginResource(Resource) :
# 로그인 하는 API
def post(self) :
# 1. 클라이언트에게 데이터 받기
data = request.get_json()
if 'email' not in data or 'password' not in data :
return {'result':'fail'}, 400
if data['email'].strip() == '' or data['password'].strip() == '' :
return {'result':'fail'}, 400
# 2. DB 로 부터 email에 해당하는 유저 정보를 가져온다.
try :
connection = get_connection()
query = '''
select *
from user
where email = %s;'''
recode = (data['email'],)
cursor = connection.cursor(dictionary=True)
cursor.execute( query, recode )
# fetchall 은 리스트로 값을 가져온다. 그래서 커서를 딕셔너리는 트루로 해줌
# 딕셔너리로 하는 이유 : 키, 벨류로 데이터 가져오는게 편하기 때문이다.
result_list = cursor.fetchall()
print(result_list)
cursor.close()
connection.close()
except Error as e:
if cursor is not None :
cursor.close()
if connection is not None :
connection.close()
return {"result":"fail", "error":str(e)}, 500
# 3. 회원인지 확인한다. 아니면 클라이언트에게 리턴
# API 명세서에 에러코드 설명을 적어준다.
if result_list == [] :
return {"result":"fail"}, 401
# 4. 비밀번호를 체크한다.
# 유저가 입력한 비밀번호 data['password']
# DB에 암호화된 비번 result_list[0]['password']
isCorrect = check_password(data['password'], result_list[0]['password'])
if isCorrect == False :
return {"result":"fail"}, 401
# 5. 유저아이디를 가져온다.
user_id = result_list[0]['id']
# 6. JWT 토큰을 만든다.
access_token = create_access_token(user_id)
# 7. 클라이언트에 응답한다.
return {"result":"success", "access_token":access_token}, 200
1-4. 포스트맨에서 로그인 잘 되는지 테스트
- success와 함께 암호화된 인증토큰이 나온다.
2. 로그아웃 API 만들기
- 생성된 토큰으로 처리하는 코드를 작성
- 토큰 정보를 받아와야 하기 때문에 app.py에 환경 변수를 세팅해야 한다.
# JWT 환경 변수 설정한 것 인식해라 라는 코드
# app.py의 임포트 항목들 밑에 작성한다.
app.config.from_object(Config)
2-1. 포스트맨에서 로그아웃 API 만들기
- 헤더 정보에 로그아웃 할 토큰 정보 입력한다.
2-2. app.py Entry point에 경로 만들기
# 경로(path)와 리소스(API 코드)를 연결한다.
# Entry point
api.add_resource( UserRegisterResource , '/users/logout' )
2-3. resources/user.py에 API 코드 작성
- 로그아웃 된 토큰을 저장할 셋(set)을 만는다 (유저파일에 만든다)
# 로그아웃된 토큰을 저장할, set 을 만든다.
jwt_blacklist = set()
class UserLogoutResource(Resource) :
# 로그아웃 하는 API
@jwt_required()
def delete(self) :
jti = get_jwt()['jti']
jwt_blacklist.add(jti)
return
- *app.py에 로그아웃된 토큰으로 요청하는 경우 처리하는 코드작성한다
# 로그아웃된 토큰으로 요청하는 경우, 처리하는 함수 작성
# 로그아웃된 토큰인지 확인하는 것
@jwt.token_in_blocklist_loader
def check_if_token_is_revoked(jwt_header, jwt_payload):
jti = jwt_payload['jti']
return jti in jwt_blacklist
2-4. 포스트맨에서 로그아웃 잘 되는지 테스트
- 로그아웃하고 토큰이 필요한 서비스가 실행되는지 확인
- 로그아웃한 토큰으로 서비스 실행 시 오류 코드
* JWT 라이브러리에서 제공하는 함수들
- create_access_token() : 토큰으로 만든다. _ 회원가입 또는 로그인 API에서 일반적으로 사용한다.
- @jwt_required(optional=False) : 무조건 토큰 필요하다.라는 의미, 옵셔널을 True로 하면 상관없다는 뜻이다.
- get_jwt_identity() : 토큰을 다시 원본데이터로 변환시켜서 가져온다.
* 에러코드 401 설명 사이트
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401
* @jwt.token_in_blocklist_loader 메뉴얼 참고 사이트
https://flask-jwt-extended.readthedocs.io/en/stable/blocklist_and_token_revoking.html
'RESTFUL API 개발' 카테고리의 다른 글
[Restful API] Flask에서 JWT 사용 _ 5. 토큰 유효기간 만드는 방법 (0) | 2024.05.24 |
---|---|
[Postman] 포스트맨 토큰 테스트 환경 셋팅 _Postman URL 변수 사용하기 (0) | 2024.05.23 |
[Restful API] Flask에서 JWT 사용 _ JWT 설치하기, 토큰을 적용한 회원가입 API (0) | 2024.05.22 |
[Restful API] 이메일 주소 형식이 올바른지 확인하는 방법 _email-validator (0) | 2024.05.22 |
[Restful API] 비밀번호 단방향 암호화와 확인하는 코드 _ pbkdf2_sha256 사용 (0) | 2024.05.22 |