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