基于Flask的 api(四)

restful安全认证

Flask-HTTPAuth是一个简单的扩展,它简化了使用Flask路由的HTTP身份验证的使用

 安装 Flask-HTTPAuth

pip install Flask-HTTPAuth

认证方式有 Basic 、Digest、token

1.Basic认证

使用HTTP基本身份验证来保护路由

from flask import Flask,jsonify
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
auth = HTTPBasicAuth()
users = {
    "aaa": generate_password_hash("123"),
    "bbb": generate_password_hash("456")
}

@auth.verify_password
def verify_password(username, password):
    if username in users and 
            check_password_hash(users.get(username), password):
        return username

@app.route('/')
@auth.login_required
def index():
    return "Hello, %s!" % auth.current_user()

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

测试

$ curl  -i http://localhost:5000
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    19  100    19    0     0     81      0 --:--:-- --:--:-- --:--:--    81HTTP/1.0 401 UNAUTHORIZED
Content-Type: text/html; charset=utf-8
Content-Length: 19
WWW-Authenticate: Basic realm="Authentication Required"
Server: Werkzeug/1.0.1 Python/3.6.0
Date: Mon, 23 Nov 2020 15:24:26 GMT

Unauthorized Access

使用curl时添加 -u (或 - user )

$ curl -u aaa:123 -i http://localhost:5000
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    11  100    11    0     0     15      0 --:--:-- --:--:-- --:--:--    15HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 11
Server: Werkzeug/1.0.1 Python/3.6.0
Date: Mon, 23 Nov 2020 15:24:44 GMT

Hello, aaa!

将验证添加到获取资源上

from flask import Flask,jsonify
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
auth = HTTPBasicAuth()
users = {
    "aaa": generate_password_hash("123"),
    "bbb": generate_password_hash("456")
}

@auth.verify_password
def verify_password(username, password):
    if username in users and 
            check_password_hash(users.get(username), password):
        return username

@app.route('/')
@auth.login_required
def index():
    return "Hello, %s!" % auth.current_user()

tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]

@app.route("/tasks", methods=['GET'])
@auth.login_required
def get_tasks():
    return jsonify({'tasks': tasks})

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

测试

$ curl -i http://localhost:5000/tasks
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    19  100    19    0     0     80      0 --:--:-- --:--:-- --:--:--    80HTTP/1.0 401 UNAUTHORIZED
Content-Type: text/html; charset=utf-8
Content-Length: 19
WWW-Authenticate: Basic realm="Authentication Required"
Server: Werkzeug/1.0.1 Python/3.6.0
Date: Mon, 23 Nov 2020 15:33:14 GMT

Unauthorized Access

Bei@DESKTOP-LCBJFJ2 MINGW64 /d/Python/dxfWrite
$ curl -u aaa:123 -i http://localhost:5000/tasks
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   317  100   317    0     0    751      0 --:--:-- --:--:-- --:--:--   751HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 317
Server: Werkzeug/1.0.1 Python/3.6.0
Date: Mon, 23 Nov 2020 15:33:19 GMT

{
  "tasks": [
    {
      "description": "Milk, Cheese, Pizza, Fruit, Tylenol",
      "done": false,
      "id": 1,
      "title": "Buy groceries"
    },
    {
      "description": "Need to find a good Python tutorial on the web",
      "done": false,
      "id": 2,
      "title": "Learn Python"
    }
  ]
}

2.Digest

使用HTTP摘要式身份验证

from flask import Flask,jsonify
from flask_httpauth import HTTPDigestAuth

app = Flask(__name__)
app.config['SECRET_KEY'] = 'key123456'
auth = HTTPDigestAuth()
users = {
    "aaa": "123",
    "bbb": "456"
}

@auth.get_password
def get_pw(username):
    if username in users:
        return users.get(username)
    return None

@app.route('/')
@auth.login_required
def index():
    return "Hello, %s!" % auth.username()

tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]

@app.route("/tasks", methods=['GET'])
@auth.login_required
def get_tasks():
    return jsonify({'tasks': tasks})

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

测试

说明:

  a.客户端访问一个受http摘要认证保护的资源

  b.服务器返回401状态以及nonce等信息,要求客户端进行认证

  c.客户端将以用户名,密码,nonce值,HTTP方法, 和被请求的URI为校验值基础而加密(默认为MD5算法)的摘要信息返回给服务器

  d.如果认证成功,则返回相应的资源。如果认证失败,则仍返回401状态,要求重新进行认证

 3.token

from flask import Flask, g,jsonify
from flask_httpauth import HTTPTokenAuth

app = Flask(__name__)
auth = HTTPTokenAuth(scheme='Bearer')

tokens = {
    "token1": "aaa",
    "token2": "bbb"
}

@auth.verify_token
def verify_token(token):
    if token in tokens:
        return tokens[token]

@app.route('/')
@auth.login_required
def index():
    return "Hello, {}!".format(auth.current_user())

tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]

@app.route("/tasks", methods=['GET'])
@auth.login_required
def get_tasks():
    return jsonify({'tasks': tasks})

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

测试

原文地址:https://www.cnblogs.com/baby123/p/14029757.html