flask入门到起飞(十四)Token生成和配合BasicAuth使用

96
aimaile
2018.11.02 00:56 字数 208

Token生成

当下前后端分离十分流行的时候,token也用得非常的多。简单的理解就是身份令牌,一段带有很多重要含义的字符串。不仅在前后分离使用得很多,在与终端交互的时候,很多也采用这种机制。
Token的玩法有很多种,可以理解为一种自定义的协议,至于Token里面的数据内容是什么,那就看整个机制怎么设计的。

介绍一种flask中玩法,抛砖引玉

from flask import app, jsonify
from itsdangerous import TimedJSONWebSignatureSerializer, SignatureExpired, \
    BadSignature

#对应解析出、token中存储的数据,可以进行业务逻辑
@api.route('/secret', methods=['POST'])
def get_token():
    """解析令牌信息"""
    form = TokenForm().validate()
    s = TimedJSONWebSignatureSerializer(app.config['SECRET_KEY'])
    try:
        data = s.loads(form.token.data, return_header=True)
    #token过期
    except SignatureExpired:
        raise AuthFailed(msg='token is expired', error_code=1001)
    #错误token异常
    except BadSignature:
        raise AuthFailed(msg='token is invalid', error_code=1002)

    r = {
        'scope': data[0]['scope'],
        'create_at': data[1]['iat'],
        'expire_in': data[1]['exp'],
        'uid': data[0]['uid']
    }
    return jsonify(r)

 
#返回token字符串
def generate_auth_token(uid, type, scope=None,
                        expiration=5000):
    #通过flask提供的对象,传入过期时间和flask的SECRET_KEY
    """生成令牌"""
    s = TimedJSONWebSignatureSerializer(app.config['SECRET_KEY'],
                   expires_in=expiration)
    #token里面的值,是技术方案需要订的,做相关的业务逻辑验证,uid唯一值表示当前请求的客户端
    #type表示客户端类型,看业务场景进行增删
    #scope权限作用域
    #设置过期时间,这个是必须的,一般设置两个小时
    return s.dumps({
        'uid': uid,
        'type': type.value,
        'scope':scope
    }).decode('ascii')

结合BasicAuth玩转Token

处理自定义结构体向服务器发送帐号密码的时候,http协议中自带的一种方式可以传递帐号密码。
在请求header中添加键值对

1、key=Authorization
#basic空格base64加密的帐号+:+密码的数据
2、value =basic base64(aimaile:123456)
from flask import current_app, g, request
from flask_httpauth import HTTPBasicAuth
from itsdangerous import TimedJSONWebSignatureSerializer ,BadSignature, SignatureExpired

auth = HTTPBasicAuth()

#这里加了auth.login_required装饰器,一旦访问此接口,会优先进入
#@auth.verify_password装饰器装饰的方法,校验token的合法性。校验规则涉及到业务层了
@api.route('', methods=['DELETE'])
@auth.login_required
def delete_user():
    uid = g.user.uid
    with db.auto_commit():
        user = User.query.filter_by(id=uid).first()
        user.delete()
    return “success”

#这个装饰器的作业就是BasicAuth中AOP接口,请求先进入这个函数,进行token相关校验
@auth.verify_password
def verify_password(token, password):
    user_info = verify_auth_token(token)
    if not user_info:
        return False
    else:
        # request
        g.user = user_info
        return True

def verify_auth_token(token):
    s = Serializer(current_app.config['SECRET_KEY'])
    try:
        data = s.loads(token)
    except BadSignature:
        raise AuthFailed(msg='token is invalid',
                         error_code=1002)
    except SignatureExpired:
        raise AuthFailed(msg='token is expired',
                         error_code=1003)
    uid = data['uid']
    ac_type = data['type']
    scope = data['scope']
    # request 视图函数
    allow = is_in_scope(scope, request.endpoint)
    if not allow:
        raise Forbidden()
    return User(uid, ac_type, scope)
flask
Gupao