python 笔记16--Flask-BasicAuth 使用与重构
原创
©著作权归作者所有:来自51CTO博客作者昕光xg的原创作品,请联系作者获取转载授权,否则将追究法律责任
python 笔记16--Flask-BasicAuth 使用与重构
1 介绍
Flask-BasicAuth 是一种Flask 扩展,它可以通过HTTP基础访问认证来保护部分视图或者全部应用。如下图,用户最开始访问应用的时候会弹出用户密码输入框,输入成功后才能访问应用。
默认情况下 Flask-BasicAuth 只支持单用户认证,而实际大部分应用是多用户认证,因此需要在其基础上加以调整。本文对 Flask-BasicAuth 原理进行介绍,并通过简单的案例重写其认证模块,实现一个简单的多用户登录功能。
2 方案
2.1 BasicAuth 使用与原理
flask BasicAuth 基础案例如下, 只需要引入 BasicAuth、配置 app.config、实例化BasicAuth,就可以使用BasicAuth了。
其中,app.config[‘BASIC_AUTH_FORCE’]为True 就默认对所有 api 进行认证, 如果设置为 False, 那么可以通过 @basic_auth.required 对指定 api 进行认证。
案例1: 对所有 api 进行认证
from flask import Flask
from flask_basicauth import BasicAuth
app = Flask(__name__)
app.config['BASIC_AUTH_USERNAME'] = 'admin'
app.config['BASIC_AUTH_PASSWORD'] = '123456'
app.config['BASIC_AUTH_FORCE'] = True
basic_auth = BasicAuth(app)
@app.route('/')
def hello_world(): # put application's code here
return 'Hello World!'
@app.route('/bye')
def bye():
return 'Good Bye!'
if __name__ == '__main__':
app.run()
案例2: 只对 /bye 进行认证
from flask import Flask
from flask_basicauth import BasicAuth
app = Flask(__name__)
app.config['BASIC_AUTH_USERNAME'] = 'admin'
app.config['BASIC_AUTH_PASSWORD'] = '123456'
app.config['BASIC_AUTH_FORCE'] = False
basic_auth = BasicAuth(app)
@app.route('/')
def hello_world(): # put application's code here
return 'Hello World!'
@app.route('/bye')
@basic_auth.required
def bye():
return 'Good Bye!'
if __name__ == '__main__':
app.run()
Flask-BasicAuth 核心源码:
Flask-BasicAuth 当前所有源码才60多行,下面贴出其主要部分;其中,init_app 中 require_basic_auth会判断 api 是否需要认证,若需要认证 check_credentials 就会将用户输入的账密信息和 app 默认的 BASIC_AUTH_USERNAME/BASIC_AUTH_PASSWORD 进行对比,通过即可正常返回数据。
# 默认路径 lib/python3.x/site-packages/flask_basicauth.py
class BasicAuth(object):
def __init__(self, app=None):
if app is not None:
self.app = app
self.init_app(app)
else:
self.app = None
def init_app(self, app):
app.config.setdefault('BASIC_AUTH_FORCE', False)
app.config.setdefault('BASIC_AUTH_REALM', '')
@app.before_request
def require_basic_auth():
if not current_app.config['BASIC_AUTH_FORCE']:
return
if not self.authenticate():
return self.challenge()
def check_credentials(self, username, password):
correct_username = current_app.config['BASIC_AUTH_USERNAME']
correct_password = current_app.config['BASIC_AUTH_PASSWORD']
return username == correct_username and password ==
2.2 BasicAuth 优化重构
上面已经提到了BasicAuth 通过默认账密和 check_credentials 来进行用户验证,因此只需要重写 check_credentials 功能就可以实现一个个性化的多账号认证功能。
重新的 new_basicauth:
vim new_basicauth.py
import base64
from functools import wraps
from flask import current_app, request, Response
__version__ = '0.2.0'
def check_user_password(username, password):
local_users = {
'admin': 'pass0',
'admin1': 'pass1',
'admin2': 'pass2'
}
if username in local_users.keys() and password == local_users[username]:
return True
else:
return False
class BasicAuth(object):
def __init__(self, app=None):
if app is not None:
self.app = app
self.init_app(app)
else:
self.app = None
def init_app(self, app):
app.config.setdefault('BASIC_AUTH_FORCE', False)
app.config.setdefault('BASIC_AUTH_REALM', '')
@app.before_request
def require_basic_auth():
if not current_app.config['BASIC_AUTH_FORCE']:
return
if not self.authenticate():
return self.challenge()
def check_credentials(self, username, password):
print(request.authorization)
return check_user_password(username, password)
def authenticate(self):
auth = request.authorization
return (
auth and auth.type == 'basic' and
self.check_credentials(auth.username, auth.password)
)
def challenge(self):
realm = current_app.config['BASIC_AUTH_REALM']
return Response(
status=401,
headers={'WWW-Authenticate': 'Basic realm="%s"' % realm}
)
def required(self, view_func):
@wraps(view_func)
def wrapper(*args, **kwargs):
if self.authenticate():
return view_func(*args, **kwargs)
else:
return self.challenge()
return
测试结果:
如下图, admin 和 admin1 都通过了, 即重写 check_credentials 后就支持多用户认证了。
3 注意事项
- 本为了内容精简,直接在 check_user_password 中内置了几个用户模拟效果,实际中可以在 db 中查找用户是否存在, 也可以从 ldap 中查询。即可以按需对接其它账号系统或者 db,实现个性化的多用户认证。
4 说明
flask-basicauth.readthedocs.io/en/latestPython编程:Flask-BasicAuth实现Authentication登录认证