身份验证令牌的空闲超时

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