flask 简单flask-httpauth验证

2018-02-11 14:08:42来源:oschina作者:阿豪boy人点击

分享

确保我们的 web service 安全服务的最简单的方法是要求客户端提供一个用户名和密码。在常规的 web 应用程序会提供一个登录的表单用来认证,并且服务器会创建一个会话为登录的用户以后的操作使用,会话的 id 以 cookie 形式存储在客户端浏览器中。然而 REST 的规则之一就是 “无状态”, 因此我们必须要求客户端在每一次请求中提供认证的信息。


我们一直试着尽可能地坚持 HTTP 标准协议。既然我们需要实现认证我们需要在 HTTP 上下文中去完成,HTTP 协议提供了两种认证机制:Basic 和 Digest。


有一个小的 Flask 扩展能够帮助我们,我们可以先安装 Flask-HTTPAuth:


$ flask/bin/pip install flask-httpauth

比方说,我们希望我们的 web service 只让访问用户名 miguel 和密码 python 的客户端访问。 我们可以设置一个基本的 HTTP 验证如下:


from flask.ext.httpauth import HTTPBasicAuth
auth = HTTPBasicAuth()
@auth.get_password
def get_password(username):
if username == 'miguel':
return 'python'
return None
@auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 401)

get_password 函数是一个回调函数,Flask-HTTPAuth 使用它来获取给定用户的密码。在一个更复杂的系统中,这个函数是需要检查一个用户数据库,但是在我们的例子中只有单一的用户因此没有必要。


error_handler 回调函数是用于给客户端发送未授权错误代码。像我们处理其它的错误代码,这里我们定制一个包含 JSON 数据格式而不是 HTML 的响应。


随着认证系统的建立,所剩下的就是把需要认证的函数添加 @auth.login_required 装饰器。例如:


@app.route('/todo/api/v1.0/tasks', methods=['GET'])
@auth.login_required
def get_tasks():
return jsonify({'tasks': tasks})

如果现在要尝试使用 curl 调用这个函数我们会得到:


$ curl -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 36
WWW-Authenticate: Basic realm="Authentication Required"
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 06:41:14 GMT
{
"error": "Unauthorized access"
}

为了能够调用这个函数我们必须发送我们的认证凭据:


$ curl -u miguel:python -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 316
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 06:46:45 GMT
{
"tasks": [
{
"title": "Buy groceries",
"done": false,
"description": "Milk, Cheese, Pizza, Fruit, Tylenol",
"uri": "http://localhost:5000/todo/api/v1.0/tasks/1"
},
{
"title": "Learn Python",
"done": false,
"description": "Need to find a good Python tutorial on the web",
"uri": "http://localhost:5000/todo/api/v1.0/tasks/2"
}
]
}

认证扩展给予我们很大的自由选择哪些函数需要保护,哪些函数需要公开。


为了确保登录信息的安全应该使用 HTTP 安全服务器(例如:https://...),这样客户端和服务器之间的通信都是加密的,以防止传输过程中第三方看到认证的凭据。


让人不舒服的是当请求收到一个 401 的错误,网页浏览都会跳出一个丑陋的登录框,即使请求是在后台发生的。因此如果我们要实现一个完美的 web 服务器的话,我们就需要禁止跳转到浏览器显示身份验证对话框,让我们的客户端应用程序自己处理登录。


一个简单的方式就是不返回 401 错误。403 错误是一个令人青睐的替代,403 错误表示 “禁止” 的错误:


@auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 403) from flask_httpauth import HTTPBasicAuth
auth = HTTPBasicAuth()
from flask import Flask, make_response, jsonify
app = Flask(__name__)@auth.get_password
def get_password(username):
if username == 'miguel':
return 'python'
return None@auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 401)@app.route('/', methods=['GET'])
@auth.login_required
def get_tasks():
return jsonify({'tasks': 'succ'})app.run(port=80)

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台