前言
- 命名文件不要用“token.py”,會報無法導入xxx類等異常
- 在restful設計中,用戶認證模式通常使用json web token,而不會使用傳統的HTTP Basic認證(傳入賬號密碼)
- token認證模式如下:在請求header中加入token(傳入賬號密碼)

Flask中的實現
flask擴展flask-httpauth提供了該認證方法
$ pip install flask-httpauth
首先實例化
auth = HTTPTokenAuth(scheme='JWT')
校驗token的方法(token_auth.py)
from flask_httpauth import HTTPTokenAuth
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired
from config import Config
from home.libs.error_code import AuthFailed
auth = HTTPTokenAuth(scheme='JWT')
@auth.verify_token
def verify_token(token):
# Config.SECRET_KEY:內部的私鑰,這里寫在配置信息里
s = Serializer(Config.SECRET_KEY)
try:
data = s.loads(token)
except BadSignature:
# AuthFailed 自定義的異常類型
raise AuthFailed(msg='token不正確')
except SignatureExpired:
raise AuthFailed(msg='token過期')
# 校驗通過返回True
return True
生成token的方法,放在了modeles.user類中生成
from config import Config
from home import db
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
class User(db.Model):
"""用戶"""
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(80), unique=True, nullable=False) # 用戶名
hash_password = db.Column(db.String(120), nullable=False) # 密碼
phone = db.Column(db.String(20), nullable=False) # 手機號
# 明文密碼(只讀)
@property
def password(self):
raise AttributeError('不可讀')
# 寫入密碼,同時計算hash值,保存到模型中
@password.setter
def password(self,value):
self.hash_password = generate_password_hash(value)
# 檢查密碼是否正確
def check_password(self, password):
return check_password_hash(self.hash_password,password)
# 生成token
@staticmethod
def create_token(user_id):
"""
生成token
:param user_id: 用戶id
:return:
"""
# 第一個參數是內部的私鑰,這里寫在配置信息里,如果只是測試可以寫死
# 第二個參數是有效期(秒)
s = Serializer(Config.SECRET_KEY, expires_in=Config.TOKEN_EXPIRATION)
# 接收用戶id轉換與編碼
token = s.dumps({"id": user_id}).decode('ascii')
return token
使用裝飾器
from flask import request, jsonify
from home.modles import User
@api.route('/login', methods=['POST'])
def login():
'''
接受參數並校驗參數,返回token
:return:
'''
# user = request.json['username']
# password = request.json['password']
# guest = User.query.filter_by(username=user).first()
# # 生成token
# z_token = User.create_token(guest.id)
#
# return jsonify(token=z_token)
pass
# 調用該裝飾器認證token(導入token_auth.py中的auth:from home.utils.token_auth import auth)
@api.route('/index')
@auth.login_required
def index():
return 'helllo word'