分享

Flask 用户名密码登录获取token

 Jcstone 2020-08-18

原创jcstone

一、服务端

利用Flask-HTTPAuth的Basic对用户名进行密码认证,获取token,然后提供token验证的接口范例

# 简单的用户名密码登录获取token的方式


import logging

from flask import Flask, request, g, make_response, jsonify

from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth


from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired



# from flask_restful import Api, Resource


app = Flask(__name__)


# 用户名密码方式认证,仅用于登录

basic_auth = HTTPBasicAuth()


# Token方式认证

token_auth = HTTPTokenAuth(scheme="Bearer")



users = [

    {'username''Tom''password''111111'},

    {'username''Michael''password''123456'}

]


# 用户登录后的token字典

# tokens={'id1': 'token1', 'id2': 'token2','id3': 'token3'}

tokens = {}


# 定义token加密、过期时间、盐SALT。例如SECRET_KEY="很长的一段密码" TOKEN_EXPIRATION=7200(为了验证有效期设为30秒) SALT= "我加的盐"

SECRET_KEY = "很长的一段密码"

TOKEN_EXPIRATION = 30

SALT = "我加的盐"


# token序列化签名方法

token_serializer = Serializer(SECRET_KEY, TOKEN_EXPIRATION)

# 创建token ,将生成的token添加到tokens列表中,这里用户名为id。如用户id存在,则更新token,旧token失效,不存在则生成新token,添加到tokens字典中



# 验证用户名密码是否正确

@basic_auth.get_password

def get_password(username):

    for user in users:

        if user['username'] == username:

            return user['password']

    return None



'''

# 登录成功返回成功信息,data中包含token(basic_auth仅用于登录)

# PostMan中调试Authorization中选择Basic Auth,输入用户名密码。

# curl --location --request POST 'http://127.0.0.1:5000/login' --header 'Authorization: Basic VG9tOjExMTExMQ=='

# 登录通过后根据用户名生成token

'''



@app.route('/login'methods=['POST'])

@basic_auth.login_required

def index():

    token = create_token(basic_auth.username())

    return jsonify({'code'1'msg''success''data': token})



# 登录失败返回错误信息(basic_auth仅用于登录,实际包含error_handler所有basic_auth认证错误)

@basic_auth.error_handler

def errornamepaswoed():

    return make_response(jsonify({'code'0'msg''Failed''data''错误的用户名或密码'}), 401)



def create_token(username):

    token = token_serializer.dumps({'username': username}, SALT)

    app.logger.debug(token)

    tokens[username] = token

    return token.decode('ascii')


# token 认证

# token loads后解析的是签名字典 {'username': 'Tom'},经过时效和错误签名验证后,检查当前用户名data['username']——即Tom是否在tokens字典中。Tom为示例用户名。

# 除用户名外,可以更多的签名,create_token生成token的签名(字典)和验证比较的签名要一致



@token_auth.verify_token

def verify_token(token):

    g.user = None

    app.logger.debug(token)

    try:

        data = token_serializer.loads(token, SALT)

    except SignatureExpired:

        app.logger.debug('SignatureExpired')

        return False  # valid token, but expired

    except BadSignature:

        app.logger.debug('BadSignature')

        return False  # invalid token

    except:

        return False


    app.logger.info(data)


    if 'username' in data:

        app.logger.debug("data['username']:"+data['username'])

        if data['username'in tokens:

            g.user = data['username']

            return True

    else:

        return False



@token_auth.error_handler

def errortoken_auth():

    return make_response(jsonify({'code'0'msg''Failed''data''令牌无效'}), 401)



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

    }

]


# token接口范例

@app.route('/tasks'methods=['GET'])

@token_auth.login_required

def get_tasks():

    return jsonify({'tasks':  tasks})



if __name__ == "__main__":

    app.run(debug=True)

    handler = logging.FileHandler('flask.log'encoding='UTF-8')

    handler.setLevel(logging.DEBUG)

    logging_format = logging.Formatter(

        '%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')

    handler.setFormatter(logging_format)

    app.logger.addHandler(handler)


二、客户端


import requests

from requests.auth import HTTPBasicAuth

import json


url = 'http://127.0.0.1:5000/login'


resp = requests.post(url, auth=HTTPBasicAuth('Tom''111111'))


print(resp.status_code)


print(resp.text)


body = json.loads(resp.text)


token = body["data"]


print(token)


taskurl = "http://127.0.0.1:5000/tasks"



payload = {}

headers = {

    'Authorization''Bearer '+token

}


response = requests.request("GET", taskurl, headers=headers, data=payload)


print(response.text.encode('utf8'))


    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多