我们上一次实现的接口,任何人都可以请求到数据。这样一来重要的数据,就可以被获取到。为此,我们需要对接口增加一些用户身份认证功能。提高接口数据的安全性。我们需要添加用户身份验证,以确保只有登录的用户可以访问获取数据,所以现在我们将添加用户登录和注册功能。开发功能之前,需要安装该功能需要的包。
代码语言:javascript复制$(venv) pip install passlib # 用于加密密码和验证密码
$(venv) pip install flask-jwt-extended # 用于用户身份验证
用户模型
首先,我们需要创建用户模型和模式。在app目录下,添加一个users包。然后在users目录下,新建models.py文件。完成这些后,可以开发我们的用户模型程序了。具体实现程序如下:
代码语言:javascript复制
from app import db
from passlib.hash import pbkdf2_sha256 as sha256
from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(120),unique=True,nullable=False)
password = db.Column(db.String(120),nullable=False)
def create(self):
db.session.add(self)
db.session.commit()
return self
@classmethod
def find_by_username(cls,username):
return cls.query.filter_by(username=username).first()
@staticmethod
def generate_hash(password):
return sha256.hash(password)
@staticmethod
def verify_hash(password,hash):
return sha256.verify(password,hash)
以上程序我们模型程序,我们定义的用户名和密码两个内容。还增加了按用户名查找用户的方法、生成密码和验证密码的方法。
用户SCHEMA
接下来创建schema.py文件,然后添加用户的schema,具体程序如下:
代码语言:javascript复制
from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields
from app.users.models import User
from app import db
class UserSchema(ModelSchema):
class Meta(ModelSchema.Meta):
model = User
sqla_session = db.session
id = fields.Number(dump_only=True)
username = fields.String(required=True)
接下来创建routes.py文件,这是我们添加用户登录和注册路由的地方。对于跨应用程序的用户身份验证,我们将使用JWT (JSON Web令牌)身份验证。JWT是一个开放标准,它定义了一种紧凑且自包含的方式,以JSON对象的形式安全地传输信息。JWT是目前世界上流行的一种用户授权方式。在Flask中有一个开源扩展叫做Flask-JWT- extended,它提供了JWT支持和其他有用的方法。我们在开始的已经安装好了这个扩展包。现在直接使用即可。现在我们打开app目录下的__init__.py文件,开始使用JWT的功能。
在__init__.py文件中,需要编写的程序如下:
代码语言:javascript复制from flask_jwt_extended import JWTManager # 在顶部导入
jwt = JWTManger() # 与db放在一起
jwt.init_app(app) # 添加到register_plugins函数中
用户注册与登录
完成以上程序后,我们就可以编写routes.py的程序了。
代码语言:javascript复制
from flask import request
from flask_jwt_extended import create_access_token
from app import db
from app.users import users_bp
from app.users.models import User
from app.users.schema import UserSchema
from app.utils.responses import response_with
from app.utils import responses as resp
# 注册
@users_bp.route('/register',methods=['POST'])
def create_user():
try:
data = request.get_json()
data['password'] = User.generate_hash(data['password'])
user_schema = UserSchema()
users = user_schema.load(data)
result = user_schema.dump(users.create())
return response_with(resp.SUCCESS_201)
except as Exception as e:
print(e)
return response_with(resp.INVALID_INPUT_422)
# 登录
@users_bp.route('/login',methods=['POST'])
def authenticate_user():
try:
data = request.get_json()
current_user = User.find_by_username(data['username'])
if not current_user:
return response_with(resp.SERVER_ERROR_404)
if User.verify_hash(data['password'],current_user.password):
access_token = create_access_token(identity=data['username'])
return response_with(resp.SUCCESS_201,value={'message':'Logged in as {}'.format(current_user.username),"access_token":access_token})
else:
return response_with(resp.UNAUTHORIZED_401)
except Exception as e:
return response_with(resp.INVALID_INPUT_422)
以上程序,就是我们实现的用户注册和登录功能。若想使用这个功能,我们还需要做如下两件事情。第一,编辑users目录下的__init__.py文件,添加Blueprint功能。具体程序如下:
代码语言:javascript复制from flask import Blueprint
users_bp = Blueprint('users_bp',__name__)
from app.users import routes
第二,编辑app目录下__init__.py文件,把用户的路由注册到app上。具体程序如下:
代码语言:javascript复制# 这部分程序添加到register_blueprints函数中
from app.users import users_bp
app.register_blueprint(users_bp,url_prefix='/api/users')
用户身份认证
用户身份认证过程中,我们使用flask_jwt_extended扩展包的jwt_required功能,它以装饰器的方式加到需要用户身份认证的接口上。_接下来,我们就来测试验证一下功能。
1、创建users数据库
代码语言:javascript复制$(venv) flask db migrate$(venv) flask db upgrade
2、注册用户
3、登录获取access_token
3、为接口增加用户身份认证
这里我们为获取书籍信息接口增加用户身份认证功能。打开books/目录下的routes.py文件增加如下程序:
代码语言:javascript复制from flask_jwt_extended import jwt_required # 在文件顶部导入
@jwt_required # 用户身份认证装饰器加到下面@books_bp.route('/',methods=['GET'])
4、访问获取数据信息接口 下图是请求接口,没有做用户授权的情况。
下图是请求接口,增加用户授权的情况。这里使用的Token,就是我们调用登录接口时返回的access_token信息。
如你所见,这就是保护REST接口的方法。在实际应用中,我们还可以使用电子邮件验证和限制用户注册,我们还可以启用基于用户的访问控制,不同类型的用户可以访问特定的api。本次分享内容,全文至此完。