1. 安装
pip install flask_httpauth
pip install itsdangerous
2. 创建对象
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): # 第一个参数是内部私钥 # 第二个参数是有效期(秒) 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
# 数据库配置 db = { 'host': '127.0.0.1', 'user': 'root', 'password': 'admin123', 'port': 3306, 'database': 'school', 'charset': 'utf8' } # 连接数据库操作 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
# 数据库配置
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 # 连接数据库操作 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. 测试
我这里使用到的数据库是school
其中的account
表
该表有两个字段user_id
和pwd
先向表中添加一条数据进行测试
INSERT INTO account (user_id, password) VALUES("kun", PASSWORD("admin123"))
- 直接输入路由测试
返回401错误码

- 输入错误的用户名或者密码测试
返回401错误码

- 输入正确的用户名以及密码测试
输入正确的用户名以及密码后,测试成功,获取到token
前端可以将token
存入到浏览器session
中
下次发请求加上token
,即可通过验证

- 使用有效的token测试
使用刚才生成的token进行测试,测试成功

- 使用过期的token或者错误的token测试
返回401错误码

8. 总结
-
flask_httpauth
用于获取请求中的Authorization
参数 -
itsdangerous
用于生成以及验证token
-
SECRET_KEY
密钥可自行修改 - 用户可以使用用户密码进行认证,或者使用
token
进行认证 - 在需要token认证的路由前添加
@auth.login_required
即可开启认证 - 可以在
before_request
处理程序中使用@auth.login_required
修饰器, 应用到所有请求
作者:无敌小鲁班
链接:https://www.jianshu.com/p/a360473bc9ab