Flask框架中的综合认证方案

Flask框架中的综合认证方案

1.统一处理

  • 需求: 获取用户身份
  • 分析: 除了静态资源, 基本所有视图都需要获取用户身份, 每个视图单独获取出现大量的代码冗余
  • 解决办法: 设置 请求钩子, 并通过 g变量 将数据传递给视图函数

代码示例:

from flask import Flask, session, g

app = Flask(__name__)
app.secret_key = 'test'

# 需求1: 所有视图都需要获取用户身份
# 解决办法: 用钩子函数进行封装  减少代码冗余
@app.before_request
def prepare():
    # 必须使用g变量来传递数据, 使用全局变量不能记录并发的多个请求数据
    g.name = session.get('username')

@app.route('/')
def index():
    if g.name:
        return "欢迎回来, %s" % g.name
    else:
        return '首页'

@app.route('/demo1/')
def demo1():
    print(g.name)
    return 'demo1'

@app.route('/login')
def login():
    """登录"""
    session['username'] = 'zs'
    return '登录成功'


if __name__ == '__main__':
    app.run(debug=True)

2.访问限制

  • 需求: 对指定的路由进行访问限制
  • 分析: 部分视图需要身份校验, 这部分视图每个单独校验仍会出现大量的代码冗余
  • 解决办法: 封装 装饰器 完成身份校验逻辑, 对指定视图函数设置装饰器

代码示例:

from flask import Flask, session, g, abort
from functools import wraps

app = Flask(__name__)
app.secret_key = 'test'


@app.before_request
def prepare():
    g.name = session.get('username')


@app.route('/')
def index():
    if g.name:
        return "欢迎回来, %s" % g.name

    else:
        return '首页'


@app.route('/login')
def login():
    """登录"""
    session['username'] = 'zs'
    return '登录成功'


# 需求2: 对部分视图进行访问限制  如个人中心必须登录才能访问
# 解决方案: 使用装饰器封装访问限制   减少代码冗余
def login_required(f):  # f = user

    def wrapper(*args, **kwargs):
        # 获取函数名
        print(wrapper.__name__)

        if g.name:  # 用户已登录
            return f(*args, **kwargs)  # 正常访问视图函数

        else:  # 用户未登录
            abort(401)  # 400 语法/参数错误 401 未认证  403 已认证, 权限不足  404 资源不存在  405 请求方式不支持  500 服务器错误

    return wrapper


@app.route('/user')
@login_required  # user = login_required(user)
def user():
    """个人中心"""
    return '访问 %s 的个人中心' % g.name


if __name__ == '__main__':
    print(app.url_map)
    app.run(debug=True)

补充:
functools.wraps

  • 系统内置的装饰器, 主要用于装饰器中的闭包函数
  • 作用是 将被装饰的函数(wrapper)的函数信息 替换为 指定函数(f)的函数信息 (包括name 函数名, doc 函数注释等)

flask中的函数标记是根据函数名生成的
视图函数添加装饰器login_required 后, 函数标记都会使用闭包函数名wrapper, 这样会出现函数标记冲突, 程序报错
解决办法: 给闭包函数添加装饰器functools.wraps(f), 让函数标记使用原视图函数名生成

代码示例:

# 使用装饰器封装访问限制 
def login_required(f):  # f = user

    @wraps(f)  # 会将被装饰的函数(wrapper)的函数信息替换为指定函数(f)的函数信息(__name__ 函数名, __doc__ 函数注释)
    # 设置该装饰器后, 可以让闭包函数使用原函数名, 避免函数标记出现冲突(函数标记是根据函数名来生成的)
    def wrapper(*args, **kwargs):

        if g.name: 
            return f(*args, **kwargs)  

        else: 
            abort(401)  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值