我正在尝试在基于 ServiceStack 的项目中实现记住我的功能。我不想使用基本身份验证,因为它需要在浏览器 cookie 中以明文形式存储密码,因此我需要想出一种易于维护和针对我现有数据库进行定制的替代方法。
我了解ServiceStack 自己对Remember me的支持是基于将IAuthSession
实例缓存在服务器端缓存中,默认情况下这是一个内存数据结构,在网站重新启动时会被清除(不好)。或者,缓存也可以基于 Redis 或 Memcached,这更好(缓存的数据在网站重新启动后仍然存在),但向图片添加的移动部分比我想添加的要多。
相反,我想使用我自己的数据库来实现这个功能:
表用户:
- UserID(自动递增的身份)
- 用户名
- 密码
- 电子邮件
- 姓名
- ETC...
表会话:
- SessionID(自动递增标识)
- 用户 ID(FK 到用户)
- 开始日期时间
- 结束日期时间
- 会话密钥 (GUID)
我看待事情的方式是这样的:
在登录请求时,AuthService
创建我的UserAuthSession
类的一个空实例(implements IAuthSession
)并调用我的自定义凭据提供程序的TryAuthenticate
方法,该方法根据用户表对用户进行身份验证,填充UserAuthSession
相关的用户数据并将新记录插入到会话表中。
然后身份验证会话缓存在内存缓存中,并创建 ServiceStack 会话 cookie (ss-id
和ss-pid
) 并将其发送到浏览器。
如果用户选中记住我,那么我的自定义凭据提供程序的OnAuthenticate
方法还会创建一个永久登录 cookie,其中包含用户的用户名和自动生成的Sessions.SessionKey。即使身份验证会话不再在缓存中,此 cookie 也将帮助我们跟踪用户的后续访问。
现在,假设站点已经重新启动,缓存消失了,所以当我们的用户返回站点时,他的身份验证会话无处可寻。当前的逻辑AuthenticateAttribute
将用户重定向回登录屏幕,但我想更改流程以便尝试根据我的自定义登录 cookie 识别用户,即:
- 查找从登录 cookie 中提取的用户名的最新Sessions记录
- 检查其SessionKey是否与登录 cookie 中的密钥匹配
- 如果它们匹配,则:
- 从用户表中读取用户的数据
- 创建我的自定义身份验证会话实例,用用户数据填充它并缓存它(就像在初始登录时一样)
- 插入具有新SessionKey值的新Sessions记录
- 将新的登录 cookie 发送回浏览器以供下次使用
- 如果密钥不匹配,则将用户发送回登录屏幕。
上面的逻辑有意义吗?
有没有人已经使用 ServiceStack 实现了类似的东西?
如果我要继续使用这种方法,不涉及创建我自己的自定义版本的最佳行动方案是AuthenticateAttribute
什么?即,我可以使用哪些钩子来使用现有的 ServiceStack 代码构建它?