1.增加配置信息
# 密钥
SECRET_KEY = '\x88D\xf09\x91\x07\x98\x89\x87\x96\xa0A\xc68\xf9\xecJ:U\x17\xc5V\xbe\x8b\xef\xd7\xd8\xd3\xe6\x98*4'
# token 超时时长
TOKEN_EXPIRATION = 30 * 24 * 3600
2.在USER类中定义验证用户身份的方法
@staticmethod
def verify(account, password):
user = User.query.filter_by(account=account).first_or_404()
if not user.check_password(password):
raise AuthFailed()
scope = {
"allow": user.get_allow_resources(),
"forbidden": user.get_forbidden_resources()
}
return json.dumps(scope)
def check_password(self, raw):
if not self._password:
return False
return check_password_hash(self._password, raw)
3.生成令牌
# 生成令牌的程序
def generate_auth_token(uid, ac_type, scope=None,
expiration=7200):
"""生成令牌"""
s = Serializer(current_app.config['SECRET_KEY'],
expires_in=expiration)
return s.dumps({
'uid': uid,
'type': ac_type.value,
'scope': scope
})
# 验证用户身份并生成令牌
@api.route('', methods=['POST'])
def get_token():
form = ClientForm().validate_for_api()
# 验证用户名密码
scope = User.verify(form.account.data, form.password.data)
# s_dict = json.loads(scope)
# 获取有效期配置
expiration = current_app.config['TOKEN_EXPIRATION']
# 生成Token
token = generate_auth_token(form.account.data,
form.type.data,
scope,
expiration)
t = {
'token': token.decode('ascii')
}
return jsonify(t), 201
4.调用服务认证用户身份并生成令牌
5.实现验证装饰器的验证方法
auth = HTTPBasicAuth()
User = namedtuple('User', ['uid', 'ac_type', 'scope'])
@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
# 验证token
def verify_auth_token(token):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except BadSignature:
raise AuthFailed(msg='非法令牌!',
error_code=1002)
except SignatureExpired:
raise AuthFailed(msg='令牌超时!',
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)
# 判断用户是否超权
def is_in_scope(scope, endpoint):
scope = json.loads(scope)
allow = scope["allow"]
forbidden = scope["forbidden"]
splits = endpoint.split('+')
red_name = splits[0]
if red_name in forbidden:
return False
if endpoint in forbidden:
return False
if endpoint in allow:
return True
if red_name in allow:
return True
else:
return False
6.在需要进行权限控制的方法上增加装饰器
# 查询组
@api.route('/', methods=['GET'])
@auth.login_required
def get_group_by_id(id):
group = Group.get_by_id(id)
return jsonify(group)
# 调用方式 http://127.0.0.1:5000/admin/group/name?name=电信维护中心
@api.route('/name')
@auth.login_required
def get_group_by_name():
v_name = request.args.get("name")
group = Group.get_by_name(v_name)
return jsonify(group)
7.测试