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 == correct_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 wrapper

测试结果:
如下图, admin 和 admin1 都通过了, 即重写 check_credentials 后就支持多用户认证了。
在这里插入图片描述

3 注意事项

  1. 本为了内容精简,直接在 check_user_password 中内置了几个用户模拟效果,实际中可以在 db 中查找用户是否存在, 也可以从 ldap 中查询。即可以按需对接其它账号系统或者 db,实现个性化的多用户认证。

4 说明

flask-basicauth.readthedocs.io/en/latest
Python编程:Flask-BasicAuth实现Authentication登录认证

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕光xg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值