python 笔记16--Flask-BasicAuth 使用与重构

2023-10-27

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登录认证

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 笔记16--Flask-BasicAuth 使用与重构 的相关文章

随机推荐

  • Hibernate @OneToOne FetchType.LAZY不生效

    在Hibernate中 提供了懒加载功能 当需要的时候才查询具体数据 但是在使用 OneToOne关系时 FetchType LAZY看起来不会生效 当你查询一个实体类A 这个实体类A持有另一个实体类B的引用 但是A中并没有记录B的主键 这
  • 怎样正确安装超声波水位计?

    1 应保持仪表垂直安装 在安装超声波液位计时 要保证换能器的发射面和被测的平面平行 这样可以保证垂直发射到被测物体表面的声波以最大的能量返回 2 实际安装时 如果现场工况有蒸汽 易有水珠附着在探头表面 并且探头的量程比实际要测量的距离大很多
  • Python 调用 WebService

    最近做新项目用 Python 开发 作为初学者 遇到了不少问题 客户端的一个模块要调用公司网站的一些新闻 只好用 WebService 实现 WebService 搭建我就不说了 这里主要说在 Python 调用 WebService 的方
  • BGP-路由反射器、联邦实验(1.11)

    目标 1 首先需要基于该与拓扑图对172 16 0 0 16进行子网划分 题中一共需要八个网段的环回和一个骨干链路共8个网段 172 16 0 0 20 骨干 再分为八个 172 16 0 0 30 172 16 0 4 30 172 16
  • java去重复元素并打印_Java打印数组中重复元素

    Java打印数组中重复元素 1 说明 在此程序中 我们需要打印数组中存在的重复元素 这可以通过两个循环来完成 第一个循环将选择一个元素 第二个循环将通过将所选元素与其他元素进行比较来遍历整个数组 如果找到匹配项 则打印重复的元素 在上面的数
  • 仙道服务器维护,【正式服】2月14日例行更新维护公告

    为了给您提供更优质的游戏体验 诛仙手游 正式服 将于2月14日7 00 9 00进行例行维护 如遇特殊情况 开机时间将会顺延 本次更新后 等级 30级的玩家将通过邮件收到200绑定元宝更新补偿奖励 情人节特别活动 1 执子之手 与子同秀 活
  • 【面试】面试官:src和href的区别

    1 请求资源类型不同 1 href是Hypertext Reference的缩写 表示超文本引用 用来建立当前元素和文档之问的链接 常用的有 link a 2 在请求 src 资源时会将其指向的资源下载并应用到文档中 常用的有script
  • C++STL容器(上)string/vector/deque/stack/queue/list

    数据结构 研究节点和节点之间的关系 STL 算法 容器 迭代器 实现了数据结构和算法的有效分离 用来管理元素 算法和迭代器可以进行无缝连接 count v begin v end 3 统计元素3的个数 容器除了可以放基础数据类型 也可以放元
  • 字符数组、字符串数组转换成字符串【JAVA基础】

    一 字符数组to字符串 直接声明 char c a b c String s new String c 二 字符串数组to字符串 string是不可变类 利用StringBuffer String str abc dfe hij Strin
  • l130 华大低功耗mcu_HC32L110C6PA HC32L110C6UA 华大超低功耗 Cortex-M0+ 32位MCU

    HC32L110C6PA HC32L110C4UAHC32L110C6UA 华大超低功耗 Cortex M0 32位MCU HC32L110C6PA HC32L110C4UA 华大超低功耗 Cortex M0 32位MCU 超低功耗 MCU
  • BLE基础理论/Android BLE开发示例/蓝牙扫描列表数量扫描包/扫描响应包设置等

    参考 https blog csdn net qq 36075612 article details 127739150 spm 1001 2014 3001 5502 参考 https blog csdn net qq 36075612
  • 蓝桥杯:李白打酒加强版

    话说大诗人李白 一生好饮 幸好他从不开车 一天 他提着酒壶 从家里出来 酒壶中有酒 22 斗 他边走边唱 无事街上走 提壶去打酒 逢店加一倍 遇花喝一斗 这一路上 他一共遇到店 NN 次 遇到花 MM 次 已知最后一次遇到的是花 他正好把酒
  • Java变量的分类(根据作用域)

    按照作用域的不同 变量可分为 成员变量和局部变量 成员变量有两种 静态变量和实例变量 成员变量 在类中声明 作用域是整个类 局部变量 在一个方法的内部声明 作用域是整个方法 静态变量 被static关键字修饰 在内存中只有一个 被类的所有实
  • Jenkins配置定时任务

    1 点击任务后 点击配置 2 选择 构建触发器 下面的 定时构建 并设定定时规则 设置完成后 构建任务就会按照我们设置的时间定时执行了 3 设定规则 此处定时任务的格式遵循 cron 的语法 可以与 cron 的语法有轻微的差异 具体格式
  • App版本更新接口的设计

    工作这几年碰到的版本检测升级的接口也算是五花八门 啥样的都有 但肯定有的功能是有个apk的下载链接 能间接或直接提示你是强制还是非强制更新 间接是指提供你后台最新版本号 让你自己与本地版本号通过比较得出是否升级 直接就是后台接口直接返回个B
  • redhat6.9安装docker

    1 离线安装说明 内网环境需要在redhat6 9上安装docker以及docker compose 内网不能连接互联网 所以只能采用手工下载离线安装包的方式做 2 需要操作系统版本 docker支持的版本有 redhat7 redhat6
  • java类的加载顺序

    一 程序 package yy class Parent static int a 4 static System out println Parent class Chlid extends Parent static int a 5 s
  • tensorflow笔记(二十七)——重要tensor操作函数

    1 合并 多个tensor的合并主要包括2个函数 tf concat和tf stack 他们的输出参数都是list of tensor 区别是 tf concat是沿某一维度拼接shape相同的张量 拼接生成的新张量维度不会增加 tf st
  • OpenCV将多幅BMP压缩成AVI文件

    最近需要同时采集多个摄像头的视频 一般的屏幕录制软件使用不了 只能自己把一幅幅图片保存下来 再转成AVI视频 OpenCV正好提供了这类函数 所以自己做了一个简单的转换工具 主要利用的函数 CvVideoWriter cvCreateVid
  • python 笔记16--Flask-BasicAuth 使用与重构

    python 笔记16 Flask BasicAuth 使用与重构 1 介绍 2 方案 2 1 BasicAuth 使用与原理 2 2 BasicAuth 优化重构 3 注意事项 4 说明 1 介绍 Flask BasicAuth 是一种F