dede个人网站模板,焦作网站建设兼职,邯郸人才网,wordpress的功能在 Web 应用中#xff0c;我们经常需要保护我们的 api#xff0c;以避免非法访问。比如#xff0c;只允许登录成功的用户发表评论等。Flask-HTTPAuth 扩展可以很好地对 HTTP 的请求进行认证#xff0c;不依赖于 Cookie 和 Session。本文主要介绍两种认证的方式#xff1a;…在 Web 应用中我们经常需要保护我们的 api以避免非法访问。比如只允许登录成功的用户发表评论等。Flask-HTTPAuth 扩展可以很好地对 HTTP 的请求进行认证不依赖于 Cookie 和 Session。本文主要介绍两种认证的方式基于密码和基于令牌 (token)。
1、安装
$ pip install Flask-HTTPAuth2、基于密码的认证
为了简化代码这里我们就不引入数据库了。
首先创建扩展对象实例
from flask import Flask
from flask_httpauth import HTTPBasicAuth
app Flask(__name__)
auth HTTPBasicAuth()这里有一点需要注意的是我们创建了一个 auth 对象但没有传入 app 对象这跟其他扩展初始化实例有一点区别。
接着写一个验证用户密码的回调函数
from werkzeug.security import generate_password_hash, check_password_hash
# 模拟数据库
books [The Name of the Rose, The Historian, Rebecca]
users [{username: ethan, password: generate_password_hash(6666)},{username: peter, password: generate_password_hash(4567)}
]
# 回调函数
auth.verify_password
def verify_password(username, password):user filter(lambda user: user[username] username, users)if user and check_password_hash(user[0][password], password):g.user usernamereturn Truereturn False上面为了对密码进行加密以及认证我们使用 werkzeug.security 包提供的 generate_password_hash 和 check_password_hash 方法generate_password_hash 会对给定的字符串生成其加盐的哈希值check_password_hash 验证传入的明文字符串与哈希值是否一致。
然后我们在需要认证的视图函数上加上 auth.login_required 装饰器比如
app.route(/, methods[POST])
auth.login_required
def add_book():_form request.formtitle _form[title]if not title:return h1invalid request/h1books.append(title)flash(add book successfully!)return redirect(url_for(index))上面完整的代码如下
$ cat app.py
# -*- coding: utf-8 -*-
from flask import Flask, url_for, render_template, request, flash, \redirect, make_response, jsonify, g
from werkzeug.security import generate_password_hash, check_password_hash
from flask_httpauth import HTTPBasicAuth
app Flask(__name__)
app.config[SECRET_KEY] secret key
auth HTTPBasicAuth()
# 模拟数据库
books [The Name of the Rose, The Historian, Rebecca]
users [{username: ethan, password: generate_password_hash(6666)},{username: peter, password: generate_password_hash(4567)}
]
# 回调函数
auth.verify_password
def verify_password(username, password):user filter(lambda user: user[username] username, users)if user and check_password_hash(user[0][password], password):g.user usernamereturn Truereturn False
# 不需认证可直接访问
app.route(/, methods[GET])
def index():return render_template(book.html,booksbooks)
# 需要认证
app.route(/, methods[POST])
auth.login_required
def add_book():_form request.formtitle _form[title]if not title:return h1invalid request/h1books.append(title)flash(add book successfully!)return redirect(url_for(index))
auth.error_handler
def unauthorized():return make_response(jsonify({error: Unauthorized access}), 401)
if __name__ __main__:app.run(host127.0.0.1, port5206, debugTrue)$ cat templates/layout.html
!doctype html
titleHello Sample/title
div classpage{% block body %} {% endblock %}
/div
{% for message in get_flashed_messages() %}{{ message }}
{% endfor %}$ cat templates/book.html
{% extends layout.html %}
{% block body %}
{% if books %}{% for book in books %}ulli {{ book }} /li/ul{% endfor %}
{% else %}p The book doesnt exists! /p
{% endif %}
form methodpost action{{ url_for(add_book) }}input idtitle nametitle placeholderadd book typetextbutton typesubmitSubmit/button
/form
{% endblock %}3、基于 token 的认证
很多时候我们并不直接通过密码做认证比如当我们把 api 开放给第三方的时候我们不可能给它们提供密码而是对它们进行授权还可能会有时间限制比如半年或一年等。这时候我们往往通过一个令牌也就是 token 来做认证Flask-HTTPAuth 提供了 HTTPTokenAuth 对象来做这件事。 例如
from flask import Flask, g
from flask_httpauth import HTTPTokenAuth
app Flask(__name__)
auth HTTPTokenAuth(schemeToken)
tokens {secret-token-1: john,secret-token-2: susan
}
# 回调函数验证 token 是否合法
auth.verify_token
def verify_token(token):if token in tokens:g.current_user tokens[token]return Truereturn False
# 需要认证
app.route(/)
auth.login_required
def index():return Hello, %s! % g.current_user
if __name__ __main__:app.run()上面我们在初始化 HTTPTokenAuth 对象时传入了 scheme‘Token’。这个 scheme是我们在发送请求时在 HTTP 头 Authorization 中要用的 scheme 字段。用 curl 测试如下
$ curl -X GET -H Authorization: Token secret-token-1 http://localhost:5000/结果
Hello, john!4、使用 itsdangerous 库来管理令牌
上面的令牌还是比较薄弱的在实际使用中我们需要使用加密的签名Signature作为令牌它能够根据用户信息生成相关的签名并且很难被篡改。itsdangerous 提供了上述功能在使用之前请使用 pip 安装: $ pip install itsdangerous。
改进后的代码如下
# -*- coding: utf-8 -*-
from flask import Flask, g
from flask_httpauth import HTTPTokenAuth
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
app Flask(__name__)
app.config[SECRET_KEY] secret key here
auth HTTPTokenAuth(schemeToken)
# 实例化一个签名序列化对象 serializer有效期 10 分钟
serializer Serializer(app.config[SECRET_KEY], expires_in600)
users [john, susan]
# 生成 token
for user in users:token serializer.dumps({username: user})print(Token for {}: {}\n.format(user, token))
# 回调函数对 token 进行验证
auth.verify_token
def verify_token(token):g.user Nonetry:data serializer.loads(token)except:return Falseif username in data:g.user data[username]return Truereturn False
# 对视图进行认证
app.route(/)
auth.login_required
def index():return Hello, %s! % g.user
if __name__ __main__:app.run()将上面代码保存为 app.py在终端运行可看到类似如下的输出
$ python app.py
Token for John: eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ3NjY5NzE0NCwiaWF0IjoxNDc2Njk1MzQ0fQ.eyJ1c2VybmFtZSI6IkpvaG4ifQ.vQu0z0Pos2Tgt5jBYMY5IYWUkTK9k3wE_RqvYHDqtyM
Token for Susan: eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ3NjY5NzE0NCwiaWF0IjoxNDc2Njk1MzQ0fQ.eyJ1c2VybmFtZSI6IlN1c2FuIn0.rk8JaTRwag0qiF9_KuRodhw6wx2ZWkOEhFln9hzOLP0* Running on http://127.0.0.1:5000/ (Press CTRLC to quit)使用 curl 测试如下
$ curl -X GET -H Authorization: Token eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ3NjY5NzE0NCwiaWF0IjoxNDc2Njk1MzQ0fQ.eyJ1c2VybmFtZSI6IkpvaG4ifQ.vQu0z0Pos2Tgt5jBYMY5IYWUkTK9k3wE_RqvYHDqtyM http://localhost:5000/
# 结果
$ Hello, john!