我们的Rails应用程序使用Restful Authentication进行用户/会话管理,似乎从多台计算机登录到同一帐户会导致其他计算机上的会话被杀死,从而导致"记住我"功能.
所以说我在家里登录应用程序(并检查"记住我").然后我去办公室登录(并检查"记住我").然后,当我回到家时,我返回到应用程序,并且必须重新登录.
如何允许从多台计算机登录并保持"记住我"功能的所有功能?
你这样做会牺牲一些安全感,但这绝对是可能的.有两种方法可以实现这一目标.
在第一个中,您可以覆盖用户模型中的make_token方法.该模型目前实施如下.
def make_token secure_digest(Time.now, (1..10).map{ rand.to_s }) end
每次用户登录时,无论是否有cookie,make_token
都会调用该方法,该方法为remember_token
用户生成并保存新内容.如果您有一些其他无法猜到的用户独有的值,则可以替换该make_token
方法.
def make_token secure_digest(self.some_secret_constant_value) end
这将确保令牌永远不会更改,但它也可以使获得令牌的任何人模仿用户.
除此之外,如果您查看文件中的handle_remember_cookie!
方法authenticated_system.rb
,您应该能够更改此方法以适合您.
def handle_remember_cookie!(new_cookie_flag) return unless @current_<%= file_name %> case when valid_remember_cookie? then @current_<%= file_name %>.refresh_token # keeping same expiry date when new_cookie_flag then @current_<%= file_name %>.remember_me else @current_<%= file_name %>.forget_me end send_remember_cookie! end
你会发现,这个方法调用用户模型三种方法,refresh_token
,remember_me
,和forget_me
.
def remember_me remember_me_for 2.weeks end def remember_me_for(time) remember_me_until time.from_now.utc end def remember_me_until(time) self.remember_token_expires_at = time self.remember_token = self.class.make_token save(false) end # # Deletes the server-side record of the authentication token. The # client-side (browser cookie) and server-side (this remember_token) must # always be deleted together. # def forget_me self.remember_token_expires_at = nil self.remember_token = nil save(false) end # refresh token (keeping same expires_at) if it exists def refresh_token if remember_token? self.remember_token = self.class.make_token save(false) end end
所有这三种方法都重置了令牌. forget_me
将其设置为nil
,而其他两个将其设置为返回的值make_token
.您可以在用户模型中覆盖这些方法,以防止它们重置令牌(如果它已存在且未过期).这可能是最好的方法,或者你可以为handle_remember_cookie!
方法添加一些额外的逻辑,尽管这可能会更多的工作.
如果我是你,我会覆盖remember_me_until
,forget_me
以及refresh_token
在用户模式.以下应该有效.
def remember_me_until(time) if remember_token? # a token already exists and isn't expired, so don't bother resetting it true else self.remember_token_expires_at = time self.remember_token = self.class.make_token save(false) end end # # Deletes the server-side record of the authentication token. The # client-side (browser cookie) and server-side (this remember_token) must # always be deleted together. # def forget_me # another computer may be using the token, so don't throw it out true end # refresh token (keeping same expires_at) if it exists def refresh_token if remember_token? # don't change the token, so there is nothing to save true end end
请注意,通过执行此操作,您将获取保护您免受令牌窃取的功能.但这是您可以做出的成本效益决定.