在尝试进行Flask身份验证工作时,我一直在苦苦挣扎。 我正在使用以下示例:https://github.com/miguelgrinberg/REST-auth/blob/master/api.py
我在mysql数据库中有一个用户,我可以生成一个令牌,但是每当我使用它发出cURL请求时,都会获得带有 Exception Bad Signature 异常的未经授权的访问。 这是我的代码:
Users.py:
# coding=utf-8
from sqlalchemy import Column, String, Date, Integer, Numeric, Enum
from common.base import Base
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import relationship, deferred
from model.DictSerializable import DictSerializable
from passlib.apps import custom_app_context as pwd_context
from itsdangerous import (TimedJSONWebSignatureSerializer
as Serializer, BadSignature, SignatureExpired)
class Users( Base, DictSerializable ):
__tablename__ = 'users'
id = Column(Integer, primary_key = True)
username = Column(String(32), index = True)
password_hash = Column(String(128))
def __init__( self, username, password ):
self.username = username
self.password = password
def hash_password(self, password):
self.password_hash = pwd_context.encrypt(password)
def verify_password(self, password):
return pwd_context.verify(password, self.password_hash)
def generate_auth_token(self, expiration=3600):
s = Serializer('SECRET KEY', expires_in=expiration)
return s.dumps({'id': self.id})
@staticmethod
def verify_auth_token(token):
s = Serializer('SECRET KEY')
try:
data = s.loads(token)
except SignatureExpired:
return None # valid token, but expired
except BadSignature:
print("Bad signature")
return None # invalid token
user = session.query(User).filter(User.id == data['id']).first()
return user
app.py:
auth = HTTPBasicAuth('Bearer')
@auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 403)
@app.route('/v1/api/users', methods = ['POST'])
def new_user():
username = request.json.get('username')
password = request.json.get('password')
if username is None or password is None:
abort(400) # missing arguments
if session.query(Users).filter(Users.username == username).first() is not None:
abort(400) # existing user
user = Users(username, password)
user.hash_password(password)
session.add(user)
session.commit()
return jsonify({ 'username': user.username }), 201, {'Location': url_for('get_user', id = user.id, _external = True)}
@app.route('/v1/api/users/<int:id>')
def get_user(id):
user = session.query(Users.id).all()
if not user:
abort(400)
return jsonify({'username': user.username})
@auth.verify_password
def verify_password(username_or_token, password):
# first try to authenticate by token
user = Users.verify_auth_token(username_or_token)
if not user:
# try to authenticate with username/password
user = session.query(Users).filter_by(username=username_or_token).first()
if not user or not user.verify_password(password):
return False
g.user = user
return True
@app.route('/v1/api/token')
@auth.login_required
def get_auth_token():
token = g.user.generate_auth_token(3600)
return jsonify({'token': token.decode('ascii'), 'duration': 3600})
以下是使用cURL的终端中的用例:
vagrant@vagrant-ubuntu-trusty-64:~/projects$ curl -u souad:souad -i -X GET http://localhost:5000/v1/api/token
HTTP/1.0 401 UNAUTHORIZED
Content-Type: text/html; charset=utf-8
Content-Length: 19
WWW-Authenticate: Bearer realm="Authentication Required"
Server: Werkzeug/0.14.1 Python/2.7.6
Date: Wed, 03 Oct 2018 11:30:04 GMT
API的输出:
[2018-10-03 10:01:36,253] INFO in _internal: 127.0.0.1 - - [03/Oct/2018 10:01:36] "GET /v1/api/token HTTP/1.1" 401 -
bad signature
[2018-10-03 11:30:04,710] INFO in _internal: 127.0.0.1 - - [03/Oct/2018 11:30:04] "GET /v1/api/token HTTP/1.1" 401 -
我不知道为什么会得到Exception Bad Signature
?
通过Flask进行身份验证并保护某些端点的最简单方法是什么?