pip install bcrypt
pip install PyJWT
bcrypt
의 사용법은 두 가지로 나뉩니다. 암호화
와 암호 일치 확인
(인코딩 과정)
bcrypt.hashpw(para1, para2)
를 이용 하여, 인코딩을 실시para1
: 첫번째 파라미터로는 bytes-string
이 필요 str 객체내의 encode() 메소드
를 이용하여, UTF-8 방식으로 인코딩을 해준 값을 넣어 wnsek.para2
: bcrypt.gensalt()
를 삽입하여, gensalt() : 소금생성기
=> gensalt()
메서드로 소금을 생성하면, b'바이트값드으으을'
가 리턴된다. 리턴된 값은 bytes 형으로 출력str 객체
=> bytes로 인코드
=> salt를 이용하여 암호화
=> (최종) bytes-string
객체를 얻게됨(디코딩 과정)
bytes-string
객체를 => UTF-8 방식으로 디코딩
하여 => 다시 str 객체
를 얻게됨import bcrypt
password = "password"
encrypted_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()) # str 객체, bytes로 인코드, salt를 이용하여 암호화
print(encrypted_password) # bytes-string
print(encrypted_password.decode("utf-8")) # str 객체
# 출력
b'$2b$12$6XEOimJ6msiHK7w/r7ayoO5W14cOVPLl8BPvmjhPJTWuo5RGRR.W6'
$2b$12$6XEOimJ6msiHK7w/r7ayoO5W14cOVPLl8BPvmjhPJTWuo5RGRR.W6
bcrypt.checkpw(para1, para2) 함수
를 사용하여 암호 일치여부 확인함para1
: "문자열".encode("utf-8")
<- utf-8로 인코드한 값para2
: bcrypt.hashpw()
로 나온 bytes-string
객체를 넣어준다import bcrypt
encrypted_password = bcrypt.hashpw("password".encode("utf-8"), bcrypt.gensalt())
print(bcrypt.checkpw("password".encode("utf-8"), encrypted_password))
print(bcrypt.checkpw("pessword".encode("utf-8"), encrypted_password))
# 출력
True
False
(암호화)
jwt.encode()
로 우선 jwt 인코딩을 실시합니다. 첫 번째 파라미터
로는 인코딩 하고자 하는 dict 객체
변수 json에 들어있는 dict값
두 번째 파라미터
로는 시크릿 키
secret
세 번째 파라미터
로는 알고리즘 방식
을 삽입 합니다.algorithm="HS256"
(복호화)
jwt.decode()
는 jwt.encode()로 인코딩한 JWT의 디코딩을 실시합니다. 첫 번째 파라미터
로는 디코딩 하고자 하는 bytes-string
객체변수 encoded에 들어있는 bytes-string값
두 번째 파라미터
로 시크릿 키
(단, 이는 jwt.encode() 에 넣은 시크릿 코드와 일치 하여야 합니다)secret
세 번째 파라미터로
는 알고리즘 방식
을 삽입 합니다.algorithm="HS256"
import jwt
json = {
"id": "justkode",
"password": "password"
}
encoded = jwt.encode(json, "secret", algorithm="HS256") # byte-string
decoded = jwt.decode(encoded, "secret", algorithm="HS256") # dict
print(encoded)
print(decoded)
# 출력
b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6Imp1c3Rrb2RlIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9.TKGlCElSgGthalfeTlbN_giphG9AC5y5HwCbz93N0cs'
{'id': 'justkode', 'password': 'password'}
app.py
from flask import Flask
from flask_restx import Resource, Api
from auth import Auth
app = Flask(__name__)
api = Api(
app,
version='0.1',
title="Scene's API Server",
description="Scene's Todo API Server!",
terms_url="/",
contact="oneofakindscene@gmail.com",
license="MIT"
)
api.add_namespace(Auth, '/auth') # namespace에서 url 들어갈 부분 머로 들어가는지 확인해야함
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=80)
auth.py
# jwt.exceptions.DecodeError 에러가 났을경우 PyJWT 버전을 낮춰줘야한다. pip install 'PyJWT<2.0.0'
import jwt
import bcrypt
from flask import request
from flask_restx import Resource, Api, Namespace, fields
users = {}
Auth = Namespace(
name="Auth",
description="사용자 인증을 위한 API",
)
user_fields = Auth.model('User', { # Model 객체 생성
'name': fields.String(description='a User Name', required=True, example="Scene")
})
user_fields_auth = Auth.inherit('User Auth', user_fields, {
'password': fields.String(description='Password', required=True, example="password")
})
jwt_fields = Auth.model('JWT', {
'Authorization': fields.String(description='Authorization which you must inclued in header', required=True, example="eyJ0e~~~~~~~~~")
})
@Auth.route('/register')
class AuthRegister(Resource):
@Auth.expect(user_fields_auth)
@Auth.doc(responses={200: 'Success'})
@Auth.doc(responses={500: 'Register Failed'})
def post(self): # post : 계정 등록하는 역할을 하는
name = request.json['name']
password = request.json['password']
if name in users: # 이미 등록되어있으니 등록 안되고 Failed return
return {
"message": "Register Failed"
}, 500
else:
users[name] = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()) # nmae을 키로하고 value에 비밀번호 저장
return {
'Authorization': jwt.encode({'name': name}, "secret", algorithm="HS256").decode("UTF-8") # str으로 반환하여 return
}, 200
@Auth.route('/login')
class AuthLogin(Resource):
@Auth.expect(user_fields_auth)
@Auth.doc(responses={200: 'Success'})
@Auth.doc(responses={404: 'User Not Found'})
@Auth.doc(responses={500: 'Auth Failed'})
def post(self): # post : id, pw 정보 일치하는지 여부 확인 <- 여기선 왜 post를 썻을까???
name = request.json['name']
password = request.json['password']
if name not in users:
return {
"message": "User Not Found"
}, 404
elif not bcrypt.checkpw(password.encode('utf-8'), users[name]): # 비밀번호 일치 확인
return {
"message": "Auth Failed"
}, 500
else:
return {
'Authorization': jwt.encode({'name': name}, "secret", algorithm="HS256").decode("UTF-8") # str으로 반환하여 return
}, 200
@Auth.route('/get')
class AuthGet(Resource):
@Auth.doc(responses={200: 'Success'})
@Auth.doc(responses={404: 'Login Failed'})
def get(self):
header = request.headers.get('Authorization') # Authorization 헤더로 담음
if header == None:
return {"message": "Please Login"}, 404
data = jwt.decode(header, "secret", algorithm="HS256")
return data, 200
Authorization
담아서 보냈을 때