多个站点上的透明用户会话(单点登录 + 单点注销) [英] Transparent user session over several sites (single sign-on + single sign-off)

查看:20
本文介绍了多个站点上的透明用户会话(单点登录 + 单点注销)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在不同域中有多个站点:example.comexample.orgmail.example.compassport.example.org.所有网站都具有共同的外观和感觉应该共享相同的用户群.

I have several sites in different domains: example.com, example.org, mail.example.com and passport.example.org. All of the sites are having common look-and-feel and should share the same user base.

在这种极端情况下,我仍然希望所有网站透明(尽可能)使用以下关键属性共享用户会话:

And in such extreme case I still want all the sites to transparently (as much as possible) share user sessions with the following key properties:

  1. 单点登录.当用户在 passport.example.org 上登录并访问任何其他网站——他应该被视为已登录.

  1. Single sign-on. When user signs on at passport.example.org and visits any other site — he should be treated as logged in.

登录的用户在站点标题中获得Hello, $username"问候语,并且不同导航菜单,列出他们可以访问的服务.如果他没有登录,而是在问候语中有一个登录"链接,指向 passport.example.org/signon.

Logged in users get "Hello, $username" greeting in site header and different navigation menu, listing services they have access to. If he's not signed in, instead of greeting there's a "Sign on" link, pointing to passport.example.org/signon.

受信任域的列表是已知的,因此实现起来相当简单使用 OpenID 或一些自制的轻量级协议.当用户第一次点击站点,我将他重定向到 passport.example.org 上的特殊身份验证端点,然后默默地将他重定向回来,并带有身份信息(或未登录"匿名身份)包括在内.对于大多数浏览器,这是完全透明的.显然,我正在使用 nonce 值来对抗重定向循环.

The list of trusted domains is known, so this is fairly simple to implement either with OpenID or with some homebrewn lightweight protocol. When user first hits the site, I'm redirecting him to special authentication endpoint at passport.example.org, which then silently redirects him back, with identity information (or "not signed on" anonymous identity) included. For most browsers this is completely transparent. Obviously, I'm using nonce values to fight redirection loops.

单点签收.当用户在任何站点的标题中单击注销"时下次他访问任何网站时 - 他应该被视为未登录".

Single sign-off. When user clicks "sign off" in the header of any site the next time he visits any site — he should be seen as "not sign on".

OpenID 不是为此而设计的.我目前的想法(我已经有一个部分工作的实现)不是发送用户身份,而是发送全局"会话令牌和共享数据库中的全局会话表(global_session_token ↔ 用户关系).

OpenID was not designed for this. My current idea (I already have a partially-working implementation) is to send not user identity, but "global" session token and share global sessions table (global_session_token ↔ user relation) in DB.

支持机器人和无 cookie 用户.网站有公共区域,应该可由用户代理访问,无需任何 cookie 支持.

Robots and cookieless-users support. Sites are having public areas, which should be accessible by user-agents without any cookie support.

因此,我在(1)中提到的重定向成为一个问题,因为对于每一个页面请求,我最终都会将用户代理扔到 auth 端点并返回.这不仅会混淆机器人,还会污染我的会话数据库出生时死亡会议非常快.而且我绝对不想显示嘿,你没有启用cookies,走开!"页面,那将是非常粗鲁和令人失望.虽然我需要 cookie 支持才能登录,但我希望用户可以自由阅读网站的用途等等——没有任何限制.

Because of this, redirection I've mentioned in (1) becomes a problem, because for every single page request, I'll end up throwing user-agent to auth endpoint and back. Not only this will confuse robots, but it will pollute my session database with dead-on-birth sessions very quickly. And I definitely don't want to display "hey, you don't have cookies enabled, go away!" page, that'd be extremely rude and disappointing. While I require cookie support to login, I want users to freely read what the sites are for and so on — without any restrictions.

而且我明确不想想把会话 ID 放在 URL 中,除了一些透明的我提到的跨域重定向.我相信这样做是一个安全问题并且通常是坏事.

And I explicitly don't want to put session IDs in URLs except for some transparent cross-domain redirections I've mentioned. I believe doing such is a security problem and just generally a Bad Thing.

这里我几乎没有想法了.

And here I'm almost out of ideas.

好吧,我知道这很难,但 Google 实际上通过 (google.com,google.lot‑of‑gTLDgmail.com 等等),对吧?所以这应该是可能.

Okay, I know this is hard, but Google actually does this somehow with (google.com, google.lot‑of‑gTLDs, gmail.com and so on), right? So this should be possible.

如果提供协议描述想法(最好)或链接,我将不胜感激到系统(要阅读的代码或仅用于观看和学习的实时站点)成功实施了这样的事情.

I'd be grateful for either protocol description ideas (that'd be the best) or links to systems (either code to read or just live sites to watch and learn upon) already successfully implementing something like this.

总结:几个没有共同根的域,共享用户群,单点登录,单点注销,匿名浏览不需要cookie.

To sum it up: Several domains without common root, shared user base, single sign-on, single sign-off, no cookies required to browse anonymously.

所有站点都在同一网络上(但位于不同的服务器上)并且部分站点共享同一个 PostgreSQL 数据库(在同一个数据库的不同方案中休息).大多数站点是用 Python/Django 编写的,但其中一些站点使用 PHP 和 Ruby on Rails.虽然我正在考虑一些与框架和语言无关的东西,但我很感激指出任何实现.即使我无法使用它们,如果我能了解它是如何完成的,也许我就能想出实现类似的东西.

All of the sites are on the same network (but rest on different servers) and partially share the same PostgreSQL database (resting in the different schemes of the same database). Most of sites are written with Python/Django, but some of them are using PHP and Ruby on Rails. While I'm thinking of something framework- and language-agnostic, I'm grateful for pointing to any implementations. Even if I won't be able to use them, if I'll get the idea how it's done there maybe I'll be able to come up implementing something similar.

推荐答案

那么,让我进一步解释一下.(所有 URL 都是虚构的!)正如我所说,访问者转到 http://www.yourwebpage.com 和表示他想登录.他被重定向到 http://your.loginpage.org?return=http://www.yourwebpage.com/Authenticated 他必须在其中提供他的用户名和密码.
当他的帐户信息有效时,他将返回登录 URL 中提供的页面,但带有将用作 ID 的附加参数.因此,他转到 http://www.yourwebpage.com/Authenticated?ID=SharedSecret 其中 SharedSecret 将是一个临时 ID,有效期为 30 秒或更短.
当您的身份验证页面被调用时,该页面将调用在 yourwebpage.com 和 loginpage.org 之间共享的方法来查找 SharedSecret 的帐户信息以检索更永久的 ID.此永久 ID 存储在 yourwebpage.com 的网络会话中,不应向用户显示.
共享方法可以是任何东西.如果两台服务器在同一台机器上,它们就可以访问同一个数据库.否则,它们可能会通过 Web 服务与另一台服务器通信.这将是服务器到服务器的通信,因此用户是机器人还是没有 cookie 支持都没有关系.这部分用户不会注意到.
您唯一需要处理的是用户的会话.通常,用户会收到一个存储在 cookie 中的会话 ID,但它也可以作为 GET 请求的一部分作为 URL 的一部分.不过,通过在表单中​​添加一个隐藏的输入字段,在 POST 请求中包含会话 ID 会更安全.

幸运的是,一些 Web 开发语言已经提供会话支持,因此您甚至不必担心维护会话和发送会话 ID.不过,这项技术很有趣.并且您需要注意会话应该始终是临时的,因为存在会话 ID 被劫持的风险.

如果您必须处理不同域上的多个站点,那么您首先需要处理一些服务器到服务器的通信.最简单的方法是让他们共享同一个数据库,但最好围绕这个数据库构建一个 Web 服务,以提供额外的保护.确保此 Web 服务仅接受来自您自己域的请求,以增加更多保护.
当您有服务器到服务器的连接时,用户将能够在您的域之间切换,只要您将会话 ID 传递到新域,用户就会登录.如果用户正在使用cookie,会话丢失的可能性不大,需要重新登录.如果没有 cookie,如果会话 ID 在浏览页面之间丢失,用户可能必须再次登录才能获取新的 cookie.(例如,访问者访问 Google,然后返回到您的网站.使用 cookie,可以从 cookie 中读取会话.如果没有 cookie,会话将丢失,因为 Google 不会转发会话 ID.

请记住,在不同域之间传递会话 ID 存在安全风险.会话 ID 可能会被劫持,从而使其他人有可能冒充您的访问者.因此,会话 ID 应该是短暂的和混淆的.但即使黑客获得了会话 ID 的访问权限,他仍然无法完全访问帐户本身.他将无法拦截服务器到服务器的通信,因此他无法使用您的用户信息访问数据库,除非他直接进入登录页面.

Well, let me explain a bit further then. (All URLs are fictional!) As I said, the visitor goes to http://www.yourwebpage.com and indicates he wants to log in. He is redirected to http://your.loginpage.org?return=http://www.yourwebpage.com/Authenticated where he will have to provide his username and password.
When his account information is valid, he will return to the page that was provided in the login URL, but with an additional parameter that will be used as ID. Thus, he goes to http://www.yourwebpage.com/Authenticated?ID=SharedSecret where SharedSecret would be a temporary ID, valid for 30 seconds or less.
When your authentication page gets called, the page would then call a method that's shared between yourwebpage.com and loginpage.org to look for the account information of SharedSecret to retrieve a more permanent ID. This permanent ID is stored in the web session of yourwebpage.com and should NEVER be shown to the user.
The shared method could be anything. If both servers are on the same machine, they could just both access the same database. Otherwise, they might communicate with another server through web services. This would be server-to-server communication thus it doesn't matter if the user is a robot or has no cookie support. This part won't be noticed by the user.
The only thing you'll have to deal with is the session for the user. Normally, users will be sent a session ID that's stored in a cookie but it can also be part of the URL as part of a GET request. It's a bit more secure to have the session ID inside a POST request, though, by adding a hidden input field to your form.

Fortunately, several web development languages do already provide session support so you don't even have to worry about maintaining sessions and sending session ID's. The technique is interesting, though. And you need to be aware that sessions should always be temporary since there's a risk that session ID's get hijacked.

If you have to deal with multiple sites on different domains then you will need to work on some server-to-server communication first. The easiest would be by letting them share the same database but it's better to build a web service around this database, for additional protection. Make sure this web service only accepts requests from your own domains just to add even a bit more protection.
When you have server-to-server connections, then the user will be able to switch between your domains and as long as you're passing along a session ID to the new domain, the user will be logged in. If the user is using cookies, it's not very likely that the session gets lost which would require to log in again. Without cookies, there's a chance that the user will have to log in again to get a new cookie if the session ID gets lost between browsing pages. (For example, the visitor goes to visit Google and then goes back to your site. With a cookie, the session could be read from the cookie. Without a cookie the session is lost since Google won't pass the session ID forwards.

Do keep in mind that passing on session ID's between different domains is a security risk. The session ID can be hijacked, thus making it possible for someone else to impersonate your visitor. Therefore, session ID's should be short-lived and obfuscated. But even if a hacker gains access to a session ID, he still won't have full access to the account itself. He won't be able to intercept the server-to-server communication so he can't access the database with your user information, unless he goes to the login page directly.

这篇关于多个站点上的透明用户会话(单点登录 + 单点注销)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆