Flask(6)

On a regular basisΒ·2021λ…„ 12μ›” 9일
0

Eager to learn Flask πŸ”₯

λͺ©λ‘ 보기
6/7

JWT 토큰 μ΄μš©ν•œ 둜그인/인증 κΈ°λŠ₯

μ™œ? JWT 토큰을 μ΄μš©ν•΄μ„œ 둜그인/인증을 ν•΄μ•Όν•˜λŠ” 걸까?
κΈ°μ‘΄ 인증 μ‹œμŠ€ν…œμ€ μ„œλ²„μΈ‘μ—μ„œ μœ μ €μ˜ 정보λ₯Ό κΈ°μ–΅ν•˜κ³  μžˆμ–΄μ•Ό ν–ˆλ‹€. κ·Έλž˜μ„œ 이 μ„Έμ…˜μ„ μœ μ§€ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ©”λͺ¨λ¦¬/λ””μŠ€ν¬/db에 이걸 λ‹΄μ•˜μ–΄μ•Όν–ˆλ‹€.

μ΄λŸ°μ‹μœΌλ‘œ! 근데 이게 μ•ˆμ’‹μ€κ²Œ μœ μ €κ°€ 인증할 λ•Œ μ„œλ²„λŠ” 그럼 이 기둝을 μ„œλ²„μ— μ €μž₯을 ν•΄μ•Όν•œλ‹€. 이게 μ„Έμ…˜ 방식. 근데 ν•œ 두λͺ…도 μ•„λ‹ˆκ³  λͺ‡ 백만λͺ…μ˜ 기둝을 μ €μž₯ν•΄μ•Ό ν•œλ‹€λ©΄ μ„œλ²„κ°€ 터지겠지? λ¬Όλ‘  db에 μ €μž₯ν•  μˆ˜λ„ μžˆμ§€λ§Œ db μ„±λŠ₯에도 무리가 갈 수 μžˆμœΌλ‹ˆ.
μ„Έμ…˜μ„ μ‚¬μš©ν•˜λ©΄ μ„œλ²„λ₯Ό ν™•μž₯ν•˜λŠ” 것도 μ–΄λ €μ›Œμ§€λŠ” 것. νŠΈλž˜ν”½λ„ λ§Žμ•„μ§€κ³  μ΄λŸ°μ €λŸ° 어렀움듀.
κ·Έλž˜μ„œ 토큰 기반의 JWTλ₯Ό μ‚¬μš©ν•œλ‹€. 그럼 이 JWTλŠ” 기쑴의 방법을 λ³΄μ™„ν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©μ΄ 될 것이닀.

쿠킀와 μ„Έμ…˜, JWT 세가지 비ꡐ

  • λŒ€λΆ€λΆ„μ˜ 웹은 쿠킀와 μ„Έμ…˜μ„ μ΄μš©ν•œ 인증 방식을 톡해 둜그인 κΈ°λŠ₯을 κ΅¬ν˜„
  • μ‚¬μš©μžκ°€ μ„œλ²„μ— μ˜¬λ°”λ₯Έ 아이디와 νŒ¨μŠ€μ›Œλ“œλ₯Ό μ „λ‹¬ν•˜λ©΄, μ„œλ²„μ—μ„œ 인증 절차λ₯Ό 거친 ν›„, ν•΄λ‹Ή μ„Έμ…˜κ°’μ„ μ„œλ²„ 내에 μƒμ„±ν•œλ‹€. μƒμ„±ν•œ μ„Έμ…˜μ„ λ°”νƒ•μœΌλ‘œ μ„Έμ…˜ IDλ₯Ό μƒμ„±ν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ λ„˜κ²¨μ£ΌλŠ”λ°, μ‚¬μš©μžμ˜ λΈŒλΌμš°μ €λŠ” 이것을 쿠킀에 μ €μž₯ν•˜μ—¬, 인증을 μš”μ²­ν•  λ•Œλ§ˆλ‹€ ν•΄λ‹Ή μΏ ν‚€λ₯Ό λ³΄λƒ„μœΌλ‘œμ¨ 둜그인 인증을 μˆ˜ν–‰
  • μ„Έμ…˜ 기반 인증의 λŒ€ν‘œμ μΈ 단점은 λ°”λ‘œ "μ„œλ²„"μ—μ„œ μ„Έμ…˜ 정보λ₯Ό μ €μž₯ν•˜κ³  μžˆλ‹€λŠ” 것.
    -> λΈŒλΌμš°μ €λ₯Ό 끄더라도 λ‹€μ‹œ 접속할 경우, 둜그인이 μœ μ§€λ˜μ–΄ μžˆλŠ” 컨셉이 μœ ν–‰ν•˜λ©΄μ„œ μ„Έμ…˜ μ €μž₯μ†Œμ˜ μ €μž₯된 정보 = νšŒμ› μˆ˜μ— λΉ„λ‘€ν•˜κ²Œ λ˜μ—ˆκ³  점점 μ„œλ²„κ°€ κ΄€λ¦¬ν•˜λŠ” μ •λ³΄μ˜ 양이 λŠ˜μ–΄λ‚˜κ²Œ 된 것. 즉, μ„œλ²„κ°€ μ„Έμ…˜ μ €μž₯μ†Œλ₯Ό μ‚¬μš©ν•˜λ―€λ‘œ μš”μ²­μ΄ λ§Žμ„ 경우 μ„œλ²„μ— λΆ€ν•˜κ°€ λŠ˜μ–΄λ‚œλ‹€.
  • JWTλŠ” μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° λ„μž…λœ ν΄λΌμ΄μ–ΈνŠΈ 기반의 인증 방식
  • μ›λž˜ μ„œλ²„μ— μ €μž₯ν•΄μ•Ό ν•  μ„Έμ…˜ 값을 κ·Έλƒ₯ 각 μ‚¬μš©μžμ—κ²Œ λͺ¨λ‘ λ„˜κ²¨λ²„λ¦¬μžλŠ” 것이닀. 그리고 인증 μ‹œμ— ν•΄λ‹Ή ν† ν°μ˜ μœ νš¨μ„±μ„ 검증할 λͺ¨λ“ˆ ν•˜λ‚˜λ§Œ 있으면 이것 μžμ²΄κ°€ μ„Έμ…˜ μ €μž₯μ†Œ 전체λ₯Ό λŒ€μ²΄ν•˜λŠ” μˆ˜λ‹¨μ΄ λ˜λŠ” 것이닀.
  • JWTλŠ” μ‚¬μš©μžμ˜ κ³ μœ μ„±μ„ μž…μ¦ν•  λ§Œν•œ 데이터λ₯Ό 포μž₯ν•˜μ—¬ 토큰을 μƒμ„±ν•œλ‹€. 그리고 ν•΄λ‹Ή 토큰을 ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ μ „μ†‘λ°›μ•˜μ„ λ•Œ, ν•΄λ‹Ή ν† ν°μ•ˆμ— λ“€μ–΄μžˆλ˜ 고유 λ°μ΄ν„°λ‘œ μ‚¬μš©μžλ₯Ό μ‹λ³„ν•˜μ—¬, λ³„λ„μ˜ 인증 과정없이 λ°”λ‘œ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 있게 λœλ‹€.
  • 단, ν•΄λ‹Ή 토큰은 ν΄λΌμ΄μ–ΈνŠΈμ— μ €μž₯λœλ‹€λŠ” 점에 λ³΄μ•ˆμ΄ μ·¨μ•½ν•  μš°λ €κ°€ 있기 λ•Œλ¬Έμ— μ‚¬μš©μžμ— λŒ€ν•œ λ―Όκ°ν•œ 정보λ₯Ό μ €μž₯ν•˜λŠ” 것은 ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  ν•œλ‹€.

πŸ₯• μ˜ˆμ „μ— μ •λ¦¬ν•΄λ’€λ˜ jwtλ₯Ό μ°Έκ³ ν•΄μ„œ λ‹€μ‹œ 읽어보기!: https://velog.io/@majaeh43/JWT

  • μ‹€μ œλ‘œ μ½”λ“œλ₯Ό 쳐보자 🐀

μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ κΈ°λ³Έ μ„ΈνŒ… ν•˜κΈ°

from flask import Flask
from flask_jwt_extended import *

application = Flask(import_name = __name__)

application.config.update(
    DEBUG = True,
    JWT_SECRET_KEY = "get some sleep"
)
# # 토큰 생성에 μ‚¬μš©λ  Secret Keyλ₯Ό flask ν™˜κ²½ λ³€μˆ˜μ— 등둝

jwt = JWTManager(application)

@application.route("/")
def test1():
    return "<h2>hola, soy Ria!<h2>"

if __name__ == '__main__':
    application.run(port = 5000,
                    debug = True)
  • 여기에 hostλ₯Ό 0.0.0.0으둜 μ€¬λŠ”λ° OSError: [Errno 49] Can't assign requested address 이런 였λ₯˜κ°€ λ–΄λ‹€. μ™œμΌκΉŒ. μš”μ²­λœ μ£Όμ†Œλ‘œ 할당이 μ•ˆλœλ‹€κ³ . 그럼 λˆ„κ°€ μ“°κ³ μžˆλŠ”κ±ΈκΉŒ? κΆκΈˆμ“°... μ•„μ˜ˆ μ§€μ›Œλ²„λ¦¬λ‹ˆκΉŒ μ„œλ²„κ°€ λŒμ•„κ°„λ‹€. 음?
  1. ν•΄λ‹Ή λ°±μ—”λ“œ μ‹œμŠ€ν…œμ΄ JWT κΈ°λŠ₯을 μˆ˜ν–‰ν•  수 μžˆλ„λ‘ μ„œλ“œ νŒŒν‹°λ₯Ό 등둝
from flask_jwt_extended import JWTManager
  1. JWT 토큰을 μƒμ„±ν•˜λŠ”λ° ν•„μš”ν•œ 고유의 μ‹œν¬λ¦Ώ ν‚€ 값을 μ„€μ •
application.config.update(
    DEBUG = True,
    JWT_SECRET_KEY = "get some sleep"
)
  1. JWTManagerλ₯Ό application λ³€μˆ˜μ— 등둝
jwt = JWTManager(application)

πŸ™ˆ λ”°λž€~

둜그인 API λ§Œλ“€κΈ°

🐀 μ—°μŠ΅μ΄λ‹ˆκΉŒ-

admin_id = "1234"
admin_pw = "qwer"

μš”λ ‡κ²Œλ§Œ μ •ν•΄μ£Όκ³ !

@application.route("/login", methods=['POST'])
def login_proc():

    input_data = request.get_json()
    # λ“€μ–΄μ˜€λŠ” κ°’ jsonν˜•νƒœλ‘œ λ³€ν™˜ν•΄μ„œ input_data λ³€μˆ˜μ— 넣어쀄거야
    user_id = input_data['id']
    user_pw = input_data['pw']
    
    if (user_id == admin_id and \
        user_pw == admin_pw):
        return jsonify(
            result = "success",
            # ok λ©΄ 토큰 λ°˜ν™˜!
            access_token = create_access_token(identity=user_id,
                                            expires_delta = False)
        )
    return jsonify(
        result = "Invalid Params!"
    # μ•„λ””, λΉ„λ²ˆ 일치 μ•ˆν•˜λ©΄~~~   
    )
    
if __name__ == '__main__':
    application.run(port = 5000,
                    debug = True)
  • 인증이 μ„±κ³΅ν•˜κ³  μ‚¬μš©μžμ—κ²Œ 토큰을 λ°˜ν™˜ν•΄μ£ΌκΈ° μœ„ν•΄ create_access_token() ν•¨μˆ˜λ₯Ό μ‚¬μš©. ν•΄λ‹Ή ν•¨μˆ˜μ— μž…λ ₯λ˜λŠ” μΈμžλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  • "identity": ν•΄λ‹Ή ν† ν°μ˜ κ³ μœ μ„±μ„ μ‹λ³„ν•˜κΈ° μœ„ν•œ 정보 (μ„œλ²„λŠ” ν•΄λ‹Ή 토큰을 μš”μ²­λ°›μ€ ν›„, 토큰 내에 μžˆλŠ” 이 identity값을 톡해 μ‚¬μš©μžλ₯Ό μ‹λ³„ν•˜κΈ° λ•Œλ¬Έμ— κ³ μœ ν•œ 값이 ν•„μš”ν•˜λ‹€. 단, ν΄λΌμ΄μ–ΈνŠΈ λ‹¨μ—μ„œ 계속 μœ μ§€λ˜λŠ” 정보이기 λ•Œλ¬Έμ— λΉ„λ°€λ²ˆν˜Έλ₯Ό λΉ„λ‘―ν•œ μ€‘μš” κ°œμΈμ •λ³΄λŠ” identity둜 μ§€μ •ν•˜λŠ” 것은 지양해야 함.

  • "expires_delta": ν•΄λ‹Ή ν† ν°μ˜ 만료일자 (토큰이 μœ νš¨ν•˜κ²Œ μ‚¬μš©λ  수 μžˆλŠ” λ§Œλ£ŒκΈ°κ°„μ„ μ„€μ •ν•  수 있음!)

κΈ°λΆ„μ’‹μ•™..πŸ™ˆ

νšŒμ›μ „μš© API λ§Œλ“€κ³  ν…ŒμŠ€νŠΈν•΄λ³΄κΈ°

@application.route('/user_only', methods=["GET"])
@jwt_required
def user_only():
    cur_user = get_jwt_identity()
    if cur_user is None:
        return "User Only!"
    else:
        return "Hi," + cur_user
  1. JWT μ „μš© λ°μ½”λ ˆμ΄ν„° μ‚½μž…
    flaskλŠ” ν•¨μˆ˜ μœ„μ— route() λ°μ½”λ ˆμ΄ν„°λ₯Ό μ”Œμ›Œμ€ŒμœΌλ‘œμ¨ ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό api ν•¨μˆ˜λ‘œ 등둝. νšŒμ› μ „μš© apiλŠ” λ°”λ‘œ κ·Έμ•„λž˜μ— @jwt_required λ°μ½”λ ˆμ΄ν„°λ₯Ό μΆ”κ°€ν•˜μ—¬ λ“±λ‘ν•œλ‹€. ν•΄λ‹Ή apiλŠ” λ°˜λ“œμ‹œ 토큰이 μž…λ ₯λ˜μ–΄μ•Ό ν•˜λ©°, 토큰이 μž…λ ₯λ˜μ§€ μ•Šκ±°λ‚˜ μœ νš¨ν•œ 토큰이 μ•„λ‹ˆλΌλ©΄ μ•„μ˜ˆ νŠ•κ²¨λ²„λ¦¬κ±°λ‚˜, μ μ ˆν•œ λŒ€μ²˜κ°€ κ°€λŠ₯ν•˜λ‹€!!

  2. JWT 토큰 λ‚΄μ˜ identity κ°’ 뢈러였기

cur_user = get_jwt_identity()
  • μš”μ²­κ³Ό ν•¨κ»˜ μ „μ†‘λœ 토큰을 ν™•μΈν•˜λŠ” μ½”λ“œμ΄λ‹€. ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λ©΄ 토큰 내에 이전에 토큰을 λ°œν–‰ν–ˆμ„ λ•Œ μ €μž₯ν–ˆμ—ˆλ˜ 'identity" 값을 κ°€μ Έμ˜¬ 수 μžˆλ‹€.

  • μ• μ΄ˆμ— 토큰이 없을 경우, μ• μ΄ˆμ— ν•΄λ‹Ή ν•¨μˆ˜μ— λ“€μ–΄μ˜¬ 수쑰차 μ—†μ§€λ§Œ 토큰 값이 잘λͺ»λœ 경우, κ°„ν˜Ή ν•¨μˆ˜ μ•ˆμœΌλ‘œ λ“€μ–΄μ˜¬ 수 μžˆλ‹€. λ•Œλ¬Έμ— ν•΄λ‹Ή identity 값을 기반으둜 μ•„λž˜μ²˜λŸΌ μœ νš¨ν•œ 토큰을 κ΅¬λΆ„ν•˜λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ€„ ν•„μš”κ°€ μžˆλ‹€.

  • ν† ν°μ˜ 값이 잘λͺ»λœ 경우 "User Only!"λΌλŠ” λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•˜κ³ , μ„±κ³΅ν•œ 경우, ν•΄λ‹Ή μœ μ €μ˜ id 값을 λ°˜ν™˜!

if cur_user is None:
		return "User Only!"
	else:
		return "Hi!," + cur_user
# TypeError: jwt_required.<locals>.wrapper() missing 1 required positional argument: 'fn'
# 계속 이 μ—λŸ¬κ°€ λ‚˜λŠ”λ° μ–΄λ””κ°€ 문제일까. λ°μ½”λ ˆμ΄ν„°μ—μ„œ μΈμžν•˜λ‚˜κ°€ μ•ˆλ“€μ–΄κ°”λ‹¨ μ†Œλ¦¬μΈκ°€? μ•„....

좜처1: https://tansfil.tistory.com/58
좜처2: https://blog.naver.com/shino1025/221568544633
좜처3: https://velopert.com/2350

profile
개발 기둝

0개의 λŒ“κΈ€