本系列教程分爲四個階段
1.flask restful web service
2.flask restful api
3.flask httpauth實現權限管控
4.uwsgi管理flask應用
前兩篇文章中,我們學習了基礎的web services和restful api的開發實現,在實現接口開發後,我們一般需要對接口進行加密認證,避免接口外泄導致的數據丟失等問題。
在原文中代碼分爲幾部分說明,並不直觀,而且影響連續性的學習,所以這裏筆者直接通過整段代碼的形式進行學習,並對代碼中的關鍵點進行拆分講解。
下面是實現httpauth及token認證的代碼:
import time
from flask import Flask, jsonify, url_for, request, g
from flask_restful import Api, abort
# flask SQLAlchemy模塊,實現ORM框架操作
from flask_sqlalchemy import SQLAlchemy
# flask自帶httpauth模塊,BasicAuth和tokenAuth子模塊
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
# 密碼散列加密模塊
from passlib.apps import custom_app_context as pwd_context
# jwt-- token生成模塊
import jwt
# werkzeug密碼加密模塊,有興趣的可以自行了解
# from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
api = Api(app)
# 關於flask SQLAlchemy實現ORM框架操作的一些基礎配置
app.config['SECRET_KEY'] = 'dqwecf29vbneuirjnf2i3n0f2i302n'
# 數據庫連接信息配置
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
# 是否自動提交sql執行
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
# 是否顯示修改回執
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# SQLAlchemy實例化
db = SQLAlchemy(app)
# 引入基礎認證、token認證模塊
auth = HTTPBasicAuth()
token_m = HTTPTokenAuth()
class User(db.Model):
#表名
__tablename__ = 'users'
#表字段名對應賦值屬性
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(32), index=True)
password_hash = db.Column(db.String(64))
# print(id, username, password_hash)
# def __init__(self, username, password_hash):
# self.username = username
# self.password_hash = password_hash
#生成密碼散列方法
def hash_password(self, password):
self.password_hash = pwd_context.encrypt(password)
#校驗密碼方法
def verify_password(self, password):
return pwd_context.verify(password, self.password_hash)
#生成token方法
def generate_auth_token(self):
# print(time.time())
print("self id ", self.id)
print(self.username)
print(self.password_hash)
return jwt.encode(
{'id': self.id, 'exp': time.time() + 600},
app.config['SECRET_KEY'], algorithm='HS256')
#校驗token方法
@staticmethod
def verify_auth_token(token):
try:
data = jwt.decode(token, app.config['SECRET_KEY'],
algorithms=['HS256'])
print(data)
except Exception as e:
print(e)
return False
user = User.query.get(data['id'])
print("user", user)
return user
# 在初次請求時,進行數據的表創建
# 實際開發中,此處一般會在數據庫中已經完成,研發人員只需要關注表結構,並進行對應的字段操作即可
@app.before_first_request
def create_db():
#刪除
db.drop_all()
#創建
db.create_all()
# 根據密碼登錄認證裝飾器進行請求攜帶的密碼信息校驗
@auth.verify_password
def verify_password(username_or_token, password):
user = User.query.filter_by(username=username_or_token).first()
if not user or not user.verify_password(password):
return False
g.user = user
return True
# 根據token登錄認證裝飾器進行請求攜帶的token校驗
@token_m.verify_token
def verify_token(token):
user = User.verify_auth_token(token)
g.user = user
if not user:
return False
return True
# 獲取用戶訪問信息,並根據判斷信息,添加新用戶
@app.route('/api/users', methods=['POST'])
def new_user():
username = request.json.get('username')
password = request.json.get('password')
if username is None or password is None:
abort(400) # missing arguments
if User.query.filter_by(username=username).first() is not None:
print('existing user')
abort(400) # existing user
user = User(username=username)
user.hash_password(password)
db.session.add(user)
db.session.commit()
return (jsonify({'username': user.username}), 201,
{'Location': url_for('get_user', id=user.id, _external=True)})
# 查詢指定用戶方法
@app.route('/api/users/<int:id>')
def get_user(id):
user = User.query.get(id)
if not user:
abort(400)
return jsonify({'username': user.username})
# 查詢所有用戶方法
@app.route('/api/users', methods=['GET'])
def get_all_user():
users = User.query.all()
if not users:
abort(400)
return jsonify(["{0}, {1}".format(user.username, user.password_hash) for user in users])
# 基於密碼生成token方法
@app.route('/api/token')
# 密碼登錄驗證裝飾器
@auth.login_required
def get_auth_token():
token = g.user.generate_auth_token()
return jsonify({'token': token.decode('ascii'), 'duration': 600})
# token認證方法
@app.route('/api/resource')
# token登錄驗證裝飾器
@token_m.login_required
def get_resource():
return jsonify({'data': 'Hello, %s!' % g.user.username})
@app.errorhandler(400)
def error(e):
print(e)
return '錯誤請求', 400
if __name__ == '__main__':
app.run('0.0.0.0', 8080)
以上代碼塊中,讀者可直接拷貝到IDEA中運行查看效果即可。
對應的需要了解的有,在ORM框架中,使用方法調用代替原生sql執行,如:
查詢
User.query.filter_by(username=username).first()
增加
user = User(username=username)
user.hash_password(password)
db.session.add(user)
db.session.commit()
關於具體的基於SQLAlchemy實現的ORM框架使用方法,請各位自行查詢資料瞭解學習。
代碼塊中已經對相應的模塊進行說明,在實際調用中代碼名稱已經是自解釋的,如若不瞭解,可以再搜索相關資料。
本文僅對flask的auth實現進行演示,不再過多的闡述,成年人的學習不應是喂什麼吃什麼,而是自己動手,豐衣足食。
感謝觀看。