OpenID 的创造性使用
情况
我有三个网站,它们曾经都是同一个网站。因此,他们使用单个数据库进行用户管理和身份验证。不幸的是,它们是非常独特的网站,并且已经发展到包含截然不同的功能。
当所有三个站点都只是一个站点时,我们使用了一个漂亮的布局切换器,该切换器通过键入请求的 URL 来确定要使用的样式表。但如果您使用 domain2.com
的用户登录 domain1.com
,服务器只会为您交换 URL,不会出现任何问题。
当我们向一个站点添加功能时,我们需要将这三个站点分成不同的系统,以免踩到自己的脚。向 domain1
添加功能会破坏 domain3
上不相关的系统,因此将事物分开更为明智。但我们保留了相同的用户数据库,因为它与我们的许可和订阅系统相关联。
现在,我们希望开始使用 SSL/TLS 来保护站点……这意味着它们通过 HTTPS 而不是 HTTP 进行传输。
使用 HTTP,我们将用户从一个站点版本跳到另一个站点版本时没有遇到太多问题。您可以登录这三个站点中的任何一个,服务器会检测您应该访问的站点,并将您踢到那里。由于我们使用状态服务器进行会话管理,因此您在传输中也不会丢失任何内容(相同的用户数据库、相同的会话 ID、相同的会话)。
使用 HTTPS,当我们将用户从一个站点踢到另一个站点时,我们就会失去这一点。目前,我们能做的最好的事情就是显示一个弹出窗口并解释“您打算登录 domain2.com
...请更新您的书签并重新登录”,然后再将其踢入正确的域。这是可行的,但这是一个不优雅的解决方案,让最终用户感到沮丧,而且它真的很草率。
理想的解决方案
理想情况下,用户一旦到达他们要转移到的站点,就会自动登录到该站点。因此:
- 使用
domain2.com
的用户帐户登录domain1.com
- 弹出一个窗口,解释您的错误并要求您更新书签
- 自动转移到
domain2.com
并登录,就好像您一开始就访问过该网站一样。
原始方法
实现此目的的第一个想法是重定向用户并将某种 ID 附加到 URL,并在用户访问新站点时获取适当的 GET 参数。虽然这有效并且我们可以让人们登录……但这是非常不安全的。您基本上是在创建一个任何人都可以用来作为该用户进行身份验证的令牌,并将其通过可能被拦截和假冒的线路传递。
OpenID 方法
我现在的想法是使用 OpenID 的某种变体,而且我什至不确定它是否有效(因此有这个问题)。 domain1.com
和 domain2.com
均位于我们的服务器上,受我们的控制,并使用我们的 SSL 证书。我们拥有对数据库的完全访问权限,并且一旦我们知道要恢复哪个会话,就可以在站点重定向后重新登录用户时恢复用户的会话。
当我过去使用 OpenID 时,它采用以下格式:
- 转到要使用的站点 AI,然后单击“登录”
- 被重定向到站点 B 的登录页面,我已经有一个帐户
- 登录到站点 B 并授予权限让站点 A 使用我的信息
- 重定向到站点 A 的经过身份验证的部分
我希望我们的系统复制该过程的步骤 3-4。基本上:
- 转到
domain1.com
并登录(您已经有一个帐户) - 阅读有关修复书签的消息,然后单击“确定”以重定向到正确的站点。
- 重定向到
domain2.com
的经过身份验证的部分
从我迄今为止对 OpenID 的了解来看,这似乎是可能的。为了弄清楚这一点,我已经阅读了几天 OpenID 和 OAuth。但我能找到的每个解决方案、教程和手册都描述了一个完整的 OpenID 服务器。我们不需要人们使用外部 OpenID 来对我们的系统进行身份验证,我们也不想成为 OpenID 提供商。我们只是想创建一个按照上述描述工作的解决方案。
那么,使用 OpenID 可以实现这一点吗?我们需要充实协议的哪些部分才能使其发挥作用?
The Situation
I have three websites that all used to be the same one. As a result, they use a single database for user administration and authentication. Unfortunately, they are very distinct websites and have grown to include drastically different features.
When all three sites were just one site, we used a nifty layout switcher that keyed on the requested URL to determine which stylesheets to use. But if you logged in to domain1.com
with a user from domain2.com
, the server would just swap the URL for you without a problem.
As we added features to one site, we needed to split the three into different systems to keep from stepping all over ourselves. Adding a feature to domain1
would break an unrelated system on domain3
, so keeping things separate was smarter. But we kept the same user database because it's tied in to our licensing and subscription systems.
Now, we want to begin using SSL/TLS to protect the sites ... meaning they're transferred over HTTPS rather than HTTP.
Using HTTP, we didn't have too many problems bouncing users from one site version to another. You could log in to any of the three sites, the server would detect which site you were supposed to be on, and would kick you over there. Since we're using a State Server for session management, you didn't lose anything in the transfer, either (same user database, same session ID, same session).
Using HTTPS, we lose this when we kick users from one site to another. At the moment, the best we can do is display a pop-up and explain "You meant to log in to domain2.com
... please update your bookmarks and log in again" before kicking them to the right domain. This works, but it's an inelegant solution, frustrates the end users, and it really just sloppy.
Ideal Solution
Ideally, users would be automatically logged in to the site they're being transferred to once they get there. So:
- Log in to
domain1.com
with a user account fromdomain2.com
- Get a popup explaining your mistake and asking you to update your bookmarks
- Be automatically transferred to
domain2.com
and logged in as if you'd gone there to begin with.
Original Approach
The first idea we had to accomplish this was to redirect the user and append an ID of some kind to the URL and fetch the appropriate GET parameter when they get to the new site. While this works and we can log people in ... it's very insecure. You're basically creating a token anyone could use to authenticate as that user and passing it over the wire where it could be intercepted and impersonated.
OpenID Approach
What I'm thinking now, and I'm not even sure it will work (hence the question), is to use some variation of OpenID. Both domain1.com
and domain2.com
are on our servers, under our control, and using our SSL certificates. We have full access to the database and, once we know which session to restore, can restore a user's session once logging them back in after the site redirect.
When I've used OpenID in the past, it's taken this format:
- Go to Site A I want to use and click Log In
- Be redirected to the login page for Site B, where I already have an account
- Log in to Site B and grant permission for Site A to use my information
- Be redirected to the authenticated portion of Site A
I want our system to replicate steps 3-4 of that process. Basically:
- Go to
domain1.com
and log in (you already have an account) - Read a message about fixing your bookmarks and click OK to be redirected to the right site.
- Be redirected to the authenticated portion of
domain2.com
From what I've ready about OpenID thus far, this seems possible. And I've been reading up on OpenID and OAuth for a couple of days now to figure this out. But every solution, tutorial, and manual I can find describes a fully-fleshed-out OpenID server. We don't need people to use external OpenIDs to authenticate to our system, and we don't want to become an OpenID provider either. We just want to create a solution that works following the above description.
So, is this possible using OpenID? Which parts of the protocol will we need to flesh out to make it work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不一定需要 OpenID 将用户同时登录到多个域。您可以生成从domain1.com到domain2.com的“签名重定向”,并使用“断言”作为domain2.com的url上的参数之一。
断言应包含用户ID、时间戳和使用a生成的签名。域 1 和域 2 之间共享秘密。为了防止重放攻击,domain2 应验证时间戳是否相对较新(10 分钟)。签名应通过使用共享秘密对断言进行哈希处理来生成。该签名使域 2 能够验证域 1 生成了断言,假设共享密钥仅在域 1 和域 2 之间已知。
在较高的层面上,我描述的机制相当于在 SAML 世界中生成“未经请求的断言”。 OpenID 理论上支持主动断言,但我从未见过它在实践中实现。
如果您以前没有实施过这种单点登录 (SSO) 技术,则应该非常小心,因为不正确的实施可能会允许攻击者以任何用户身份登录到domain2。
You don't necessarily need OpenID to log the user simultaneously into multiple domains. You can just generate a "signed redirect" from domain1.com to domain2.com with an "assertion" as one of the parameters on the url to domain2.com
The assertion should contain the userid, a timestamp, and a signature generated using a shared secret between domain1 and domain2. In order to prevent replay attacks, domain2 should verify that the timestamp is relatively recent (10 minutes). The signature should be generated by hashing the assertion with the shared secret. The signature enables domain2 to verify that domain1 generated the assertion, assuming that the shared secret is only known between domain1 and domain2.
At a high level, the mechanism I described is equivalent to generating an "unsolicited assertion" in the SAML world. Unsolicited assertions are theoretically supported in OpenID, but I've never seen it implemented in practice.
If you haven't implemented this sort of Single Sign On (SSO) technique before, you should be very careful, as incorrect implementations can potentially allow attackers to login to domain2 as any user.