인증은 private api와 같은 사용자를 제한해야하는 api에서 필요하며, public api와 같은 경우 사용 횟수 제한이나 남용 방지등을 위해 쓰입니다.
인증을 생성 및 사용 방법은 대략적으로 아래와 같습니다.
암호화에는 두가지 방식이 있습니다.
일반적으로 비밀번호를 암호화 할때는 단방향 암호화 방식을 사용합니다. 다만 md5나 sha1 같은 경우 rainbow table과 같은 hash table로 깨지기 쉽기 때문에 깨기 어렵게 하는 hash 알고리즘을 사용합니다.
여기서 사용할 것은 bcrypt 알고리즘입니다.
참고 : https://namu.wiki/w/암호 알고리즘
access token을 만드는 방법은 다양하지만 여기서는 많이 쓰이는 JWT를 사용합니다.
구조
header : 토큰 타입과 사용되는 해시 알고리즘을 지정합니다.
payload : 실제로 서버 간에 전송하고자 하는 데이터 부분. 다만 base64로 암호화하는거라 민감한 데이터는 넣지 말아야 합니다.
signature : BASE64URL 코드화된 header와 payload 그리고 JWT secret를 헤더에 지정된 암호 알고리즘으로 암호화하여 전송
참고 : https://medium.com/sjk5766/jwt-json-web-token-소개-49e211c65b45
우리는 http header에 access token이 있는지 특정 api에서 검사를 할 decorator를 만들어야 합니다. 다른 파일들처럼 decorator를 따로 작성합니다.
# decorator.py
import jwt
from api import *
from functools import wraps
from flask import request, Response, current_app, g
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
access_token = request.headers.get('Authorization')
if access_token is not None:
try:
payload = jwt.decode(access_token, current_app.config['JWT_SECRET_KEY'], 'HS256')
except jwt.InvalidTokenError:
payload = None
if payload is None: return Response(status = 401)
user_id = payload['user_id']
g.user_id = user_id
g.user = get_user(user_id) if user_id else None
else:
return Response(status=401)
return f(*args, **kwargs)
return decorated_function
Authorization이 필요한 API에 decorator를 설정 합니다.
# app.py
@app.route('/tweet', methods=['POST'])
@login_required
def tweet():
user_tweet = request.json
user_tweet['id'] = g.user_id
tweet = user_tweet['tweet']
if len(tweet) > 300:
return '300자를 초과했습니다.', 400
insert_tweet(user_tweet)
return '', 200
@app.route('/follow', methods=['POST'])
@login_required
def follow():
payload = request.json
payload['id'] = g.user_id
insert_follow(payload)
return '', 200
@app.route('/unfollow', methods=['POST'])
@login_required
def unfollow():
payload = request.json
payload['id'] = g.user_id
insert_unfollow(payload)
return '', 200