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)