2

在我的应用程序中,我有一个User模型,它有一个rememberable_token列。创建用户时,会在before_create过滤器中保存一个随机安全字符串,作为用户的安全令牌:

user.rememberable_token = SecureRandom.urlsafe_base64

在会话控制器中,它使用该令牌的值创建一个永久 cookie,以便用户在关闭浏览器时不会被注销,只有在他们通过logout操作注销时才会被注销:

会话控制器

def create
  .
  .
  cookies.permanent.signed[:permanent_user_session] = user.rememberable_token
end

def logout  
  cookies.delete :permanent_user_session
  redirect_to root_url  
end

cookie 在应用程序控制器中用于确定是否存在当前用户,以及在一些控制器中用于确定用户是否已登录和授权的 before_filter 中。

应用控制器

def current_user  
  @current_user ||= User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) if cookies.signed[:permanent_user_session]
end

def authorize
  unless User.find_by_rememberable_token(cookies.signed[:permanent_user_session])
    render :action => 'login'
  end
end

问题是这是安全的还是容易被会话劫持?如果它容易被劫持,如果在该session#logout方法中它在删除现有 cookie 之前为用户创建一个新的 rememberable_token (但不创建具有该值的新 cookie),会好吗?

谢谢你。

4

2 回答 2

1

如果有人在窃取 cookie,则此代码:

def current_user  
 @current_user ||= User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) if cookies.signed[:permanent_user_session]
end

仍然可以工作。在您的注销方法中,您必须从用户表中删除令牌并在登录时重新创建。

基本上,您在创建时所做的应该在每次登录时完成,并在每次注销时恢复。

于 2013-02-06T13:04:30.683 回答
0

我可能会这样做:

在会话创建时:

random_string = SecureRandom.urlsafe_base64
cookies.permanent.signed[:permanent_user_session] = random_string   
user.rememberable_token = Digest::MD5.hexdigest(random_string) && user.save

在会话销毁:

cookies.delete :permanent_user_session

在应用程序控制器中:

def current_user  
  @current_user ||= User.find_by_rememberable_token(Digest::MD5.hexdigest(cookies.signed[:permanent_user_session])) if cookies.signed[:permanent_user_session]
end

def authorize
  unless @current_user
    render :action => 'login'
  end
end

这样,您将存储令牌的哈希,并为每次新登录重新生成一个新的(并在每次注销时过期)。Rails 负责 CSRF,但长期会话可能不是一个好主意。

于 2013-02-06T14:02:59.363 回答