Flask-Httpauth
是一个Flask
扩展,可简化使用Flask
路由的HTTP
身份验证。Flask-HTTPAuth提供了多个验证方式实现验证。验证方式如下:
- HTTPBasicAuth:http基础身份验证保护路由
- HTTPDigestAuth:http摘要认证
- HTTPTokenAuth:使用Token实现路由和api的认证
- MultiAuth:多种验证方式组合

HTTPBasicAuth
Flask-HTTPAuth
扩展插件提供HTTPBasicAuth
类实现http
的基本验证实现,其实现原理图如下:

Flask-HTTPAuth
提供实现的基础认证示例如下:
from flask import Flask
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
auth = HTTPBasicAuth()
users = {
"john": generate_password_hash("hello"),
"susan": generate_password_hash("bye")
}
@auth.verify_password
def verify_password(username, password):
if username in users and \
check_password_hash(users.get(username), password):
return username
@app.route('/')
@auth.login_required
def index():
return "Hello, {}!".format(auth.current_user())
if __name__ == '__main__':
app.run()
用 verify_password
装饰器装饰的函数接收客户端发送的用户名和密码。如果凭据属于用户,则该函数应返回用户对象。如果凭据无效,该函数可以返回 None
或 False
。然后可以从身份验证实例的 current_user()
方法查询用户对象。
HTTPDigestAuth
Flask-HTTPAuth
提供HTTPDigestAuth
实现HTTP
的摘要认证。其实现通过请求头WWW-Authenticate
辅助验证,其原理图如下:

其使用示例代码如下:
from flask import Flask
from flask_httpauth import HTTPDigestAuth
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key here'
auth = HTTPDigestAuth()
users = {
"john": "hello",
"susan": "bye"
}
@auth.get_password
def get_pw(username):
if username in users:
return users.get(username)
return None
@app.route('/')
@auth.login_required
def index():
return "Hello, {}!".format(auth.username())
if __name__ == '__main__':
app.run()
HTTPTokenAuth
Flask-HTTPAuth
通过HTTPTokenAuth
实现API
和路由的登录认证。其实现原理是通过token
实现身份的认证。其实现原理如下:

其实现代码示例如下:
from flask import Flask
from flask_httpauth import HTTPTokenAuth
app = Flask(__name__)
auth = HTTPTokenAuth(scheme='Bearer')
tokens = {
"secret-token-1": "john",
"secret-token-2": "susan"
}
@auth.verify_token
def verify_token(token):
if token in tokens:
return tokens[token]
@app.route('/')
@auth.login_required
def index():
return "Hello, {}!".format(auth.current_user())
if __name__ == '__main__':
app.run()
HTTPTokenAuth
是一个通用的身份验证处理程序,可以与非标准身份验证方案一起使用,方案名称作为构造函数中的参数给出。在上面的示例中,服务器提供的 WWW-Authenticate
标头将使用 Bearer
作为方案:
WWW-Authenticate: Bearer realm="Authentication Required"
verify_token
回调接收客户端在 Authorization 标头上提供的身份验证凭据。这可以是一个简单的标记,也可以包含多个参数,函数必须从字符串中解析和提取这些参数。与 verify_password
一样,如果令牌有效,该函数应返回用户对象。
MultiAuth
应用有时需要支持身份验证方法的组合。例如,可以通过通过基本身份验证发送客户端ID
和秘密来验证Web
应用程序,而第三方API
客户端使用JWS
或JWT BEARER
令牌。 Multiauth
类允许您保护具有多个身份验证对象的路由。要授予对端点的访问,必须验证其中一种身份验证方法。
用户角色
Flask-HTTPAuth
包括一个简单的基于角色的身份验证系统,可以选择添加该系统以在过滤对路由的访问时提供额外的粒度层。要启用角色支持,请编写一个函数来返回给定用户的角色列表,并使用 get_user_roles
装饰器对其进行装饰:
@auth.get_user_roles
def get_user_roles(user):
return user.get_roles()
要限制具有给定角色的用户访问路由,请将角色参数添加到 login_required
装饰器:
@app.route('/admin')
@auth.login_required(role='admin')
def admins_only():
return "Hello {}, you are an admin!".format(auth.current_user())
role
参数可以采用角色列表,在这种情况下,具有任何给定角色的用户将被授予访问权限:
@app.route('/admin')
@auth.login_required(role=['admin', 'moderator'])
def admins_only():
return "Hello {}, you are an admin or a moderator!".format(auth.current_user())
在最高级的用法中,可以通过多个角色来过滤用户:
@app.route('/admin')
@auth.login_required(role=['user', ['moderator', 'contributor']])
def admins_only():
return "Hello {}, you are a user or a moderator/contributor!".format(auth.current_user())
部署
请注意,某些Web
服务器默认情况下不会将授权标题传递到WSGI
应用程序。例如,如果您将Apache
与MOD_WSGI
一起使用,则必须在此处记录的“ wsgipassauthorization
”设置选项。
弃用的基本身份验证选项
在上述 verify_password
存在之前,还有其他更简单的机制来实现基本身份验证。虽然这些已被弃用,但它们仍然得到维护。但是,应该首选 verify_password
回调,因为它提供了更高的安全性和灵活性。
get_password
回调需要返回与给出的用户名关联的密码。 flask-httpauth
仅在get_password
(用户名)==密码时才允许访问。例子:
@auth.get_password
def get_password(username):
return get_password_for_username(username)
通常,仅使用此回调并不是一个好主意,因为它需要密码以服务器中的明文提供。在更有可能将密码存储在用户数据库中的情况下,则需要附加回调来定义如何哈希密码:
@auth.hash_password
def hash_pw(password):
return hash_password(password)
在此示例中,您必须将hash_password()
替换为应用程序中使用的特定哈希功能。当提供hash_password
回调后,当get_password(username)== hash_password(password)
时,将授予访问权限。
如果哈希算法需要已知用户名,则回调可以进行两个参数,而不是一个参数:
@auth.hash_password
def hash_pw(username, password):
salt = get_salt(username)
return hash_password(password, salt)