38

我对如何实现共享的跨域登录系统以及最佳实践和安全预防措施很感兴趣。如果您熟悉 37Signals,您可能习惯于使用共享的通用身份验证机制,如果您使用顶级导航到不同的产品,则无需随后登录。我想以类似的方式实现一些东西。

我在网上找到的最接近的是中央身份验证服务上的维基百科条目以及对跨域登录的响应- 如何在从一个域转移到另一个域时自动登录用户,在这种情况下可能略有不同。

我检查了他们的会话 cookie 以了解他们在此过程中所做的事情。最初,每个产品链接都有一个“goto”uristub,即:

https://MY_COMPANY.campfirenow.com/id/users/[int_identifier]/goto

使用 FireCookie 和 Firebug 中的 NET 选项卡,我可以看到设置的 cookie 和过程中发生的重定向。gotourl 触发 302 重定向到:

https://MY_COMPANY.basecamphq.com/login/authenticate?sig=[BASE64_ENCODED_AND_ENCRYPTED_DATA]

会话标识符被重新创建,很可能是出于 CSRF 目的。cookie 中的一些数据以及 GET 参数 sig 使用 base64_decode 部分解密为以下内容:

// sig GET param
array(2) {
  [0]=>
���ף�:@marshal_with_utc_coercionT7�z��<k��kW"
  [1]=>
  string(18) "���k�&lt;kn8�f���to��"
}

// _basecamp_session cookie session param
string(247) {
:_csrf_token"1Sj5D6jCwJKIxkZ6oroy7o/mYUqr4R5Ca34cOPNigqkw=:session_id"%060c0804a5d06dafd1c5b3349815d863"
flashIC:'ActionController::Flash::FlashHash{:
@used{: auth{"
              MY_COMPANY{:
                       user_idi�3
:identity_idi�W����������s�]��:�N[��:

呸呸呸呸”

编码正在破坏代码块。谢谢你的帮助!

4

7 回答 7

73

I think the key in your Q is where you write "whereby you do not have to subsequently login if you use the top level navigation to a different product".

I will explain: You want to be able to move from site1.com to site2.com and let site2.com know that you are some user that logged in via site1.com.

because cookies are not shareable between different domains (other than subdomains but I guess you are not talking about sub-domains) you have to pass some information on the link to site2.com that will let it talk with its back-end and know what user you are.

lets start with a naive solution and then work our way to make resolve some of the problems that it poses: suppose you have a users table on some back-end DB and your user has some ID. now assume that the user authenticated on site1.com and he is user 123 from your DB. The most naive solution would be to call site2.com/url/whatever?myRealID=123 and have site2 check for this ID and "belive" the user that this is indeed him.

Problem: Anyone (even a valid user of your site) that will see your link can create a link with myRealID=123 or try other values for it. and site2.com will accept him as that user.

Solution: lets not use guessable ID's suppose you add to your users table a unique GUID and if user 123 has a guid of 8dc70780-15e5-11e0-ac64-0800200c9a66 then call site2.com/url/whatever?myGuid=8dc70780-15e5-11e0-ac64-0800200c9a66.

New Problem: well even though It would be very unlikely that someone will guess your user's GUID his GUID can still be hijacked by some middle man that sees this link and it someone will get the guid he can use it for ever.

Solution: Use a private key saved on your server to sign a string that contains the following data items, current time-stamp, destination site (i.e "site2.com") the said GUID, this signature can be translated into saying "This is a proof that this link was created by the site at the said time for the user that has this GUID to authenticated by this domain" and send it to site2.com along with the time-stamp and GUID. Now when site2.com gets the link he can make sure that it is signed properly and if some middleman or originally user would try to change it in any way (either by modifying the time or GUID) then the signature would not match and site2.com will refuse authenticating the user.

One last problem: if the link is intercepted by a middleman he can still use if from some other machine.

Solution: add a nonce to the passed parameters. The nonce is just a random number that your authentication system should make sure that it does not allow you to authenticate with this number more then once (hence then name N(umber)-ONCE). Note that this means that each link you create on site1.com that leads to site2.com should have a distinct nonce which needs to be saved on the back-end for later validation.

because you don't want to keep adding records to this nonce table forever it is custom to decide that such a link is only valid for some given time after its creation. and so you can create nonce records that are older than this time limit.

I hope that this is the outline you where looking for. It is possible that I missed something but those are the basic guidelines, use a signature to prove the authenticity of the data in the link and use a nonce to prevent middleman attacks. I would also recommend using HTTPS for those links if possible.

Eyal

于 2011-01-01T20:52:23.277 回答
5

You could try to implement a Global Network Auto-Login solution à la Stack Overflow.
There's an insightful post regarding its brilliant implementation by Kevin Montrose here.

It would require Cookies, HTML5 localStorage, Javascript, Iframe and a lot of security checks but I think it's worth it.

于 2011-01-05T09:47:33.147 回答
1

Allowing users the option of using their facebook/yahoo/gmail/openID solution is a start, but that doesn't ulimately solve the solution of implementing or using one's own solution.

Having developed and managed an implementation in the past (we ultimately went toward SiteMinder, but I'm guessing you don't want the cost of a real product), I think that Eyal has a very good idea, but I'd add a little tweak to it.

At the time of authentication, generate a random code (could be a GUID value, but it is not static per user) that is stored in a transactional table along with the user id. This code has a maximum lifetime (you'll need to judge the safety value for that time period). This code would ideally be either hashed with the user name or encrypted and sent across as part of the URL.

于 2011-01-04T23:01:18.580 回答
0

Have you tried something like Charles to sniff what is being sent back and forth? It might be able to break down things further for you.

As mentioned by FlipScript, perhaps using OAuth/OpenID might be a way forward for you?

于 2010-12-31T13:57:17.440 回答
0

Take a look at Jasig CAS http://www.jasig.org/cas . I think it will do what you want. It's open source, and has a number of plugins to allow you to authenticate use multiple sources of authentication and from multiple domains/languages.

于 2011-01-04T19:08:12.917 回答
0

Why no use Open ID for this purpose.

OperID will be the optimum solution for this problem.

于 2011-01-05T12:56:56.973 回答
0

Use Something Like .NET Passport (IE. Windows Live Id) Or The Way Facebook Has Done It With Their API, Which Can Be Openly Viewed.

于 2011-01-19T11:27:29.537 回答