1. 安裝
pip install flask_httpauth
pip install itsdangerous
2. 創(chuàng)建對象
from flask import Flask, g, jsonify
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
3. 生成token
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
# 密鑰瀑构,可隨意修改
SECRET_KEY = 'abcdefghijklmm'
# 生成token, 有效時間為600min
def generate_auth_token(user_id, expiration=36000):
# 第一個參數(shù)是內部私鑰
# 第二個參數(shù)是有效期(秒)
s = Serializer(SECRET_KEY, expires_in=expiration)
return s.dumps({'user_code': user_code})
4. 解析token
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous import BadSignature, SignatureExpired
# 密鑰稍刀,可隨意修改
SECRET_KEY = 'abcdefghijklmm'
# 解析token
def verify_auth_token(token):
s = Serializer(SECRET_KEY)
# token正確
try:
data = s.loads(token)
return data
# token過期
except SignatureExpired:
return None
# token錯誤
except BadSignature:
return None
5. 驗證token
# 數(shù)據(jù)庫配置
db = {
'host': '127.0.0.1',
'user': 'root',
'password': 'admin123',
'port': 3306,
'database': 'school',
'charset': 'utf8'
}
# 連接數(shù)據(jù)庫操作
def connect(user_id, password):
conn = mc.connect(**db)
cursor = conn.cursor(dictionary=True)
args = (user_id, password)
verify_sql = "SELECT user_id FROM account WHERE user_id = %s AND pwd = PASSWORD(%s);"
cursor.execute(verify_sql, args)
user = cursor.fetchone()
return user
# 驗證token
@auth.verify_password
def verify_password(username, password):
# 先驗證token
user_id = re.sub(r'^"|"$', '', username)
user_id = verify_auth_token(user_id)
# 如果token不存在表悬,驗證用戶id與密碼是否匹配
if not user_id:
user_id = connect(username, password)
# 如果用戶id與密碼對應不上校读,返回False
if not user_id:
return False
g.user_id = user_id.get('user_id')
return True
6. 完整代碼
配置文件config.py
# 數(shù)據(jù)庫配置
db = {
'host': '127.0.0.1',
'user': 'root',
'password': 'admin123',
'port': 3306,
'database': 'school',
'charset': 'utf8'
}
# 密鑰沼侣,可隨意修改
SECRET_KEY = 'abcdefghijklmm'
主文件run.py
from flask import Flask, g, jsonify
from flask_httpauth import HTTPBasicAuth
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous import BadSignature, SignatureExpired
from flask_cors import CORS
import mysql.connector as mc
from config import db, SECRET_KEY
import re
app = Flask(__name__)
CORS(app, supports_credentials=True)
auth = HTTPBasicAuth()
# 生成token, 有效時間為600min
def generate_auth_token(user_id, expiration=36000):
s = Serializer(SECRET_KEY, expires_in=expiration)
return s.dumps({'user_id': user_id})
# 解析token
def verify_auth_token(token):
s = Serializer(SECRET_KEY)
# token正確
try:
data = s.loads(token)
return data
# token過期
except SignatureExpired:
return None
# token錯誤
except BadSignature:
return None
# 連接數(shù)據(jù)庫操作
def connect(user_id, password):
conn = mc.connect(**db)
cursor = conn.cursor(dictionary=True)
args = (user_id, password)
verify_sql = "SELECT user_id FROM account WHERE user_id = %s AND pwd = PASSWORD(%s);"
cursor.execute(verify_sql, args)
user = cursor.fetchone()
return user
# 驗證token
@auth.verify_password
def verify_password(username, password):
# 先驗證token
user_id = re.sub(r'^"|"$', '', username)
user_id = verify_auth_token(user_id)
# 如果token不存在,驗證用戶id與密碼是否匹配
if not user_id:
user_id = connect(username, password)
# 如果用戶id與密碼對應不上歉秫,返回False
if not user_id:
return False
g.user_id = user_id.get('user_id')
return True
@app.route('/login')
@auth.login_required
def login():
token = generate_auth_token(g.user_id)
return jsonify({'token': token})
@app.route('/index')
@auth.login_required
def index():
return 'index'
if __name__ == '__main__':
app.run()
只需要在需要登錄驗證請求下添加裝飾器@auth.login_required
即可
7. 測試
我這里使用到的數(shù)據(jù)庫是school
其中的account
表
該表有兩個字段user_id
和pwd
先向表中添加一條數(shù)據(jù)進行測試
INSERT INTO account (user_id, password) VALUES("kun", PASSWORD("admin123"))
- 直接輸入路由測試
返回401錯誤碼
- 輸入錯誤的用戶名或者密碼測試
返回401錯誤碼
- 輸入正確的用戶名以及密碼測試
輸入正確的用戶名以及密碼后蛾洛,測試成功,獲取到token
前端可以將token
存入到瀏覽器session
中
下次發(fā)請求加上token
雁芙,即可通過驗證
- 使用有效的token測試
使用剛才生成的token進行測試再登,測試成功
- 使用過期的token或者錯誤的token測試
返回401錯誤碼
8. 總結
-
flask_httpauth
用于獲取請求中的Authorization
參數(shù) -
itsdangerous
用于生成以及驗證token
-
SECRET_KEY
密鑰可自行修改 - 用戶可以使用用戶密碼進行認證岖研,或者使用
token
進行認證 - 在需要token認證的路由前添加
@auth.login_required
即可開啟認證 - 可以在
before_request
處理程序中使用@auth.login_required
修飾器, 應用到所有請求