본문 바로가기
기록/Python

[Python] 파이썬 flask api token 체크 - db 연결 & model & SQLAlchemy

by 자임 2022. 9. 30.

 

목표 :
사용자가 key와 name 값을 파라미터에 넣어서 api를 호출하면, DB users 테이블에 있는 name-key 값이 일치하는지 확인 후, 일치할 경우에만 api 실행


코드 :

 

runserver.py

from flask import Flask, request, jsonify
from models import db
from tokenChk import tokenChk

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

# DB 설정
app.config['SECRET_KEY']='[key]'
app.config['SQLALCHEMY_DATABASE_URI'] = '[연결할 db url]'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

# 초기화
db.init_app(app)
# models.py에 db = SQLAlchemy(app) 해야 하는데 app이 없으니까 여기서 함
db.app = app
# db실행
db.create_all()


# api
@app.route("/search")
def search():

    # GET 파라미터 저장
    title = request.args.get("title", "")
    key = request.args.get("key", "")
    name = request.args.get("name", "")

    tChk = tokenChk(name)
    public_id = tChk.getPublicId()

    if public_id == key:

			~내용 생략~

        return jsonify(results)

    else:
        logger.info("KEY 값이 일치하지 않습니다.")
        return "KEY 값이 일치하지 않습니다."

		
if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8000)

 

 

 

tokenChk.py

# _*_ coding: utf-8 _*_
from models import db, Users
import log

logger = log.get_logger("tokenChk")

class tokenChk():

    def __init__(self, name):
        self.name = name

    def getPublicId(self):
        
        try:
            public_id = db.session.query(Users.public_id).filter(Users.name == self.name).first()
            public_id = public_id[0]
    
            return public_id

        except:
            logger.info("사용자가 존재하지 않습니다")
            return "사용자가 존재하지 않습니다"

 

 

 

models.py

# -*- coding: utf-8 -*-
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Users(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    public_id = db.Column(db.String(500))
    name = db.Column(db.String(100))
    password = db.Column(db.String(1000))

 

 

 

 

구조 참고 :
https://velog.io/@poiuyy0420/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Flask-DB-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0SQLAlchemy
https://dubaiyu.tistory.com/179


*
db.init_app(app)
db.app = app
db.create_all()

전역 변수로 db 객체를 만든 다음 create_app 함수 안에서 init_app 메서드를 이용해 app에 등록.


플라스크는 이러한 패턴을 자주 사용한다. db 객체를 create_app 함수 안에서 생성하면 블루프린트와 같은 다른 모듈에서 사용할수 없기 때문에 db, migrate와 같은 객체를 create_app 함수 밖에 생성하고, 해당 객체를 앱에 등록할 때는 create_app 함수에서 init_app 함수를 통해 진행한다.
출처: https://wikidocs.net/81045








+
토큰을 헤더로 받고 체크하는 게 더 나을 것 같아서 나중에 써보려고 저장하는 코드

 

def token_required(f):
   @wraps(f)
   def decorator(*args, **kwargs):

      token = None

      if 'x-access-tokens' in request.headers:
         token = request.headers['x-access-tokens']

      if not token:
         return jsonify({'message': 'a valid token is missing'})

      try:
         data = jwt.decode(token, app.config[SECRET_KEY])
         current_user = Users.query.filter_by(public_id=data['public_id']).first()
      except:
         return jsonify({'message': 'token is invalid'})
      return f(current_user, *args, **kwargs)
   return decorator