身份验证令牌的空闲超时
Idle Timeout of Authentication Tokens
我有一个使用 Flask 和 SQLAlchemy 的应用程序,允许用户使用我在登录应用程序时提供给他们的身份验证令牌调用 RESTful API。该应用程序的要求之一是,如果用户空闲 15 分钟,则他们的令牌应该过期,他们将需要再次登录应用程序以获取新令牌。
目前我通过将用户会话存储在 table
class Session(Model):
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('user.id'))
user = relationship('User')
creation_time = Column(DateTime, default=datetime.now)
last_active = Column(DateTime, default=datetime.now)
_serializer = Serializer('foobar')
def is_active(self):
return (datetime.now() - self.last_active) < timedelta(15*60)
def create_token(self, token):
return self._serializer.dumps({
'session_id': self.id,
'user_id': self.user_id,
})
@staticmethod
def from_token(self, token):
try:
data = self._serializer.loads(token)
except BadSignature:
return None
session = Session.query.get(data.get('session_id'))
if session and session.is_active() and session.user_id == data.get('user_id'):
# Refresh the session
session.last_active = datetime.now()
return session
class User(Model):
id = Column(Integer, primary_key=True)
username = Column(String)
def generate_token(self):
return Session(self.id).create_token()
def verify_auth_token(token):
session = Session.from_token(token)
if session:
return session.user
有没有更优雅、更高效的方法?我见过很多例子,其中令牌存储创建时间并且令牌仅在特定时间段内有效(这允许轻松测试而不必知道它是什么用户等),但我还没有能够根据用户的空闲时间找到有关到期的任何信息。
除了潜在的错误,因为 session.last_active = …
是在没有调用 session.flush()
(那里是 SQLAlchemy 会话)的情况下设置的,这是一种完全合理的方法。
一般来说,站点使用 non-relational 数据存储(例如 Redis)进行会话管理,因为它可以提高性能(RDBMS 的写入速度往往较慢,尤其是在这种情况下,您将很多写)。
不过逻辑还是一样的:
def session_from_token(token):
key = "session:%s" %(token, )
session_json = redis.get(key)
if not session_json:
return None
session = json.loads(session_json)
if not session.get("is_valid"):
return None
redis.expire(key, 15 * 60)
return session
我有一个使用 Flask 和 SQLAlchemy 的应用程序,允许用户使用我在登录应用程序时提供给他们的身份验证令牌调用 RESTful API。该应用程序的要求之一是,如果用户空闲 15 分钟,则他们的令牌应该过期,他们将需要再次登录应用程序以获取新令牌。
目前我通过将用户会话存储在 table
class Session(Model):
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('user.id'))
user = relationship('User')
creation_time = Column(DateTime, default=datetime.now)
last_active = Column(DateTime, default=datetime.now)
_serializer = Serializer('foobar')
def is_active(self):
return (datetime.now() - self.last_active) < timedelta(15*60)
def create_token(self, token):
return self._serializer.dumps({
'session_id': self.id,
'user_id': self.user_id,
})
@staticmethod
def from_token(self, token):
try:
data = self._serializer.loads(token)
except BadSignature:
return None
session = Session.query.get(data.get('session_id'))
if session and session.is_active() and session.user_id == data.get('user_id'):
# Refresh the session
session.last_active = datetime.now()
return session
class User(Model):
id = Column(Integer, primary_key=True)
username = Column(String)
def generate_token(self):
return Session(self.id).create_token()
def verify_auth_token(token):
session = Session.from_token(token)
if session:
return session.user
有没有更优雅、更高效的方法?我见过很多例子,其中令牌存储创建时间并且令牌仅在特定时间段内有效(这允许轻松测试而不必知道它是什么用户等),但我还没有能够根据用户的空闲时间找到有关到期的任何信息。
除了潜在的错误,因为 session.last_active = …
是在没有调用 session.flush()
(那里是 SQLAlchemy 会话)的情况下设置的,这是一种完全合理的方法。
一般来说,站点使用 non-relational 数据存储(例如 Redis)进行会话管理,因为它可以提高性能(RDBMS 的写入速度往往较慢,尤其是在这种情况下,您将很多写)。
不过逻辑还是一样的:
def session_from_token(token):
key = "session:%s" %(token, )
session_json = redis.get(key)
if not session_json:
return None
session = json.loads(session_json)
if not session.get("is_valid"):
return None
redis.expire(key, 15 * 60)
return session