Rails - 如果用户的子域被删除并且他们已登录,则重定向到用户的子域?

Rails - Redirect to a user's subdomain if it is removed and they are signed in?

我有一个多租户应用程序,通过子域具有不同的帐户。我的登录系统使用 cookie。我的应用程序控制器中有一个 current_user 助手:

def current_user
  @current_user ||= User.unscoped.find_by_auth_token(cookies[:auth_token]) if cookies[:auth_token]
end
helper_method :current_user

我使用此代码登录:

cookies[:auth_token] = {value: user.auth_token, domain: :all}

这很好用。我想做的是向用户显示他们是否在其他帐户的登录页面上登录了其他帐户。换句话说:

  1. 登录account1.derp.com
  2. 访问account2.derp.com/login
  3. Link 在底部显示(您已经登录帐户 1)。

但是,我似乎无法从其他帐户访问 cookie(这似乎是 web/browser 的预期行为)。所以在那个页面上,如果我尝试访问 cookies[:auth_token],它是零,因为 cookie 是给另一个 account/url.

此外,如果用户已登录并从 URL 中删除其子域,我想将用户重定向到与其子域相同的 URL...这需要相同的东西 - 如果子域不存在或不同,我可以访问他们帐户的 cookie。

例如,Slack 可以同时完成这两件事。尝试在登录时从页面中删除您的子域 - 您会自动重定向回带有您的子域的同一页面(它基本上只是为您将其放回原处)。或者,如果您转到另一个帐户的登录页面,它会告诉您,"You're already signed in on another account."

我正在尝试完成此操作,但是一旦我删除子域或转到其他子域,我在登录时设置的 cookies[:auth_token] 为零。我正在寻找某种方法来跟踪用户登录的位置,因此在删除子域或访问另一个子域的情况下,我知道他们已经登录到一个帐户。

有没有人对这种类型的 cookie 管理有任何经验,或者对我如何在用户登录到不同帐户时进行跟踪有任何见解?

"Multitenancy with Rails," 的作者 Ryan Bigg 通过 Twitter 对此做出了回应。

@greg_blass You need to set the domain option for the session_store to be the root domain. If you don’t do this, sessions will be scoped to where they’re set.

有效...我可以通过这种方式跨域读取所有用户 cookie:

cookies[:auth_token] = {value: user.auth_token, domain: "lvh.me"} #set lvh.me to the proper environment for production/test

我没有这样想,因为这将允许用户登录任何帐户(我的代码的工作方式)。

所以我有一个logged_in?助手,它是:

def logged_in?
  !current_user.nil?
end
helper_method :logged_in?

最后我又做了一个帮手:

def logged_in_to_current_account?
  logged_in? and request.subdomain == current_user.account.subdomain
end
helper_method :logged_in_to_current_account?

然后我的require_loginbefore_action:

def require_login
  if !logged_in_to_current_account?
    redirect_to login_url, flash: {danger: "You need to log in to see this page."}
  end
end

现在logged_in?实际上只是意味着他们在某个地方登录,也许是一个不同的帐户,我可以在上面描述的情况下使用它......我可以使用 logged_in_to_current_account? before_action 检查的助手。

然后最后回答我的问题,一旦 cookie 可以跨子域共享(并且缺少子域),此代码将重定向到同一页面,如果用户的子域被删除,则将其添加回来:

if logged_in? and request.subdomain.blank?
  redirect_to controller: controller_name, action: action_name, subdomain: current_user.account.subdomain
end

我把它连接到 before_action 中,我很高兴!