清风白茶

我们都会上岸,阳光万里,去哪里都是鲜花开放。
使用flask-httpauth给你的flask-restful-api加入请求认证

使用flask-httpauth给你的flask-restful-api加入请求认证

最近在用vue.jsflask-restful开发一个前后端分离的个人博客,其中有一个接口article用于根据文章ID对文章进行查询(get请求)、修改(post请求)等操作。显然这个接口只有查询操作能对所有用户开放而修改操作只对管理员开放。这时候就需要对aritcle接口进行请求认证,由于Restful api并不保存状态,因此也就无法使用Flask-login依赖Cookie以及session来实现认证。所有这里我使用了另一个扩展Flask-HTTPAuth

1. 重写前的接口

先来看一下重写前的接口下面是一个demo。article接口支持get、post请求,分别用于查询文章信息和修改文章信息,

用列表来存储文章数据

使用列表嵌套字典的形式,存储两个文章,每个文章包含了两个字段id用于查询文章和content存储文章的内容。

1
2
3
4
5
6
7
8
9
10
11
from flask_restful import reqparse, Resource
articles = [
{
'id': 1,
'content': "test article 1"
},
{
'id': 2,
'content': "test article 2"
}
]

使用flask-restful编写article接口

使用flask-restful编写article接口,接受两种请求getpost,分别用于查询文章和修改文章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Article(Resource):
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument('id', type=int)
self.parser.add_argument('content', type=str)

def get(self):
# 从get请求中获取文章id值
article_id = self.parser.parse_args().get('id')
# 根据id从列表中查找文章
for article in articles:
if article.get('id') is article_id:
# 返回查找到的数据
return article, 200

def post(self):
# img_file = self.parser.parse_args().get('imgFile')
# img_file.save(img_file.filename)
# 从请求中获取content值和id值
article_id = self.parser.parse_args().get('id')
content = self.parser.parse_args().get('content')
# 查找文章
for article in articles:
if article.get('id') is article_id:
res = article
# 修改文章
res['content'] = content
return res, 201

2. 使用flask-httpauth添加请求认证

我们不希望article这个接口的post请求对任何人都开放。通过引入flask-httpautharticle接口的post请求加入请求认证。Flask-HTTPAuth是一个简单的扩展,它简化了HTTP身份验证与Flask路由的使用。其提供了多种不同的Auth方法,比如HTTPBasicAuth,HTTPTokenAuth,MultiAuth和HTTPDigestAuth。这个例子中我们使用基本的密码验证,同时

2.1 安装flask-httpauth

在你的终端窗口执行:

1
pip install Flask-HTTPAuth

创建flask-httpauth对象实象。需要注意,初始化实例时不需要传入app对象,也不需要调用auth.init_app(app)注入应用对象。

1
2
from flask import Flask
from flask_httpauth import HTTPBasicAuth

2.2 使用HTTPBasicAuth

使用我们先简单的使用HTTPBasicAuth进行用户和密码认证。创建HTTPBasicAuth实例对象。为了方便演示,我们把用户名和密码存入一个字典里面。

1
2
3
4
5
6
auth_basic = HTTPBasicAuth()
# 单用户
user = {
'username':"amdin",
'password':'123456'
}
2.2.1 对article 接口添加请求认证

@auth_basic.login_required装饰器表示视图需要认证,在flask-restful编写的api中我们需要的在接口中添加类变量method_decorators。其值是一个字典形式。下面的代码表示Article接口的post和delete请求需要认证。

1
2
3
4
5
class Article(Resource):
method_decorators = {
'post': [auth_basic.login_required],
'delete': [auth_basic.login_required]
}
2.2.2 编写验证用户密码的回调函数

@auth_basic.verify_password装饰器用于验证用户名和密码。在它所修饰的函数里面返回True或者是False.

1
2
3
@auth_basic.verify_password
def verify_password(username,password):
return user['username'] == username and user['password'] == password
2.2.3 对接口进行测试

使用curl命令对接口进行测试, 会得到Unauthorized Access表示没有权限。

1
curl -d "id=1&content=modify article1" -X POST http://127.0.0.1:5000/article

加入用户名和密码后则可以正常修改文章。

1
curl -u admin:123456 -d "id=1&content=modify article1" -X POST http://127.0.0.1:5000/article
2.2.4 错误处理

在之前的例子中,如果未认证成功,服务端会返回401状态码及”Unauthorized Access”文本信息。可以通过重写错误处理方法,自定义返回的错误信息。用@auth_basic.error_handler装饰器来修饰错误处理方法:

1
2
3
4
from flask import make_response, jsonify
@auth_basic.error_handler
def auth_basic_unauthorized():
return make_response(jsonify({'res': 0, 'message': 'Unauthorized access'}), 401)

加入这个错误处理方法后,认证失败后服务器会返回JSON信息{res:0,message:Unauthorized access}.

2.2.5 使用Flask-Bcrypt

在大多数情况下,数据库中的密码是以非明文的形式存储的。可以使用Flask-Bcrypt扩展对密码进行哈希后再存储到数据库中。官方文档在这里

2.3 使用 HTTPTokenAuth

大部分情况下我们并不是使用密码和用户名进行验证的,而是使用token来做验证。Flask-HTTPAuth中的HTTPTokenAuth可以完成token验证。与HTTPBasicAuth相似,它也提供了login_required装饰器来认证视图函数,error_handler装饰器来处理错误。不同的是它没有verify_password装饰器取而代之的是verify_token。在这里我是使用一个login接口用于登录操作,登录之后将会使用用户名和密码生成一个token,存储在flask的全局变量g中,以供token验证时调用。具体代码等有时间在写吧。。。

未完。。。


评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×