Skip to content

Tag Archives: 豆瓣

豆瓣提供了一个简单的SSO应用场景

21-Mar-10

Views: 4豆瓣电台上线以后,有人在twitter上问了一句douban.com和douban.fm之间的相互认证是怎么做的,是不是用到了cross-domain cookie。 实际上,cookie本身就不是为了跨域访问的设计的,我现在还不知道有真正的跨域cookie访问存在。如果存在,在一定程度上,我也认为那是个安全漏洞。 豆瓣的这个多个域名的共享认证是个典型的跨域SSO(单点登录)案例。虽然中间机关众多,但说一下其中的道理还是很简单的。 SSO,单点登录,有几个前提概念需要先说清楚: 1. 现在的SSO,大部分场景,都由一个专门的应用来提供认证。认证功能不像以前一样是内嵌在具体应用内部的。这个提供认证的应用一般都叫做identity provider,它所在的域我们称为认证域。这个应用会在你访问的时候简历你的基础认证信息,表明你在这个域里有个基础账户和基础权限。豆瓣的identity provider是http://www.douban.com/service/account/ 2. 具体的应用,比如douban.fm,称作service provider。service provider里会有一个优先级相当高的模块负责检查用户请求是否是认证过的。如果不是,它会将当前用户请求用某种方式保留并重新导向用户到认证域去做认证。这种模块在apache里设置在最前的mod,在IIS里就是一个priority是High的ISAPI filter。它能在一切应用处理以前检查请求内的认证信息。 3. 虽然说cookie不是跨域认证的解决方案,但cookie在跨域认证的过程中却是必需的。因为HTTP协议的无状态特性,服务器端要知道新收到的请求是不是来自于过去认证过的用户,它必须在客户端留下一些信息,一般就是cookie的方式保存。也有例外,比如HTTP Basic的认证方式,cookie不参与认证,但用户名和密码是被浏览器保存在内存里的,每次都会跟随请求发送。 4. 关于整个认证流程,浏览器可能会在identity provider和service provider之间跳转多次,一些HTTP的监视工具可以帮助你发现这些跳转,比如ieHTTPHeaders。 一个简单跨域SSO的认识过程应该是这样的(以豆瓣的域名为例,但并不是说豆瓣一定就是这么做的): 用户发请求到douban.fm。douban.fm就是一个service provider,它上面的那个检查模块会先检查这个请求里有没有有效的认证信息。如果没有,它就把用户导向到http://www.douban.com/service/account/去做认证。这时的跳转URL类似http://www.douban.com/service/account/?return_to=http://douban.fm/ 。 最后的参数告诉identity provider,认证完要回到什么地方。 http://www.douban.com/service/account/作为identity provider会提示用户登录,并建立本地的认证信息,包括本域的认证cookie,和本域的session。然后根据跳转过来的URL return_to参数再把用户送回去。这时,除了return_to参数的URL以外,它还会附加一些认证相关的信息,比如在本域的认证id或者session id之类的。我刚登录的时候豆瓣重新导向我的url是http://douban.fm?sig=c3a7f19879&response_nonce=1269147513&data=%C9%ACVt%60%2C%C4K%89c%BD%07%B0Al%25%DD%F6%5D%D2%B2%E0%AC%16W%D9znW%935%AF%84%D4Vz%8C%9B%85g+%C3%C6%5D%FED9%96%84%D4Vz%8C%9B%85g+%C3%C6%5D%FED9%96&mode=id_res&return_to=http%3A%2F%2Fdouban.fm 后面的sig和response_nonce,data三个字段估计就是用于验证登录的相关信息。 当用户通过这个URL再次回到douban.fm的时候,那个检查认证的模块会发现这次回来的时候sig,response_nonce,data三个字段,然后用这三个信息从后台去identity provider寻求认证(比如socket去链接identity provider上的认证信息提供端口)。如果有效,就马上建立本地session和相关cookie信息以完成认证。然后再将请求放进具体的应用中去。这时候这个应用就得到了认证的用户信息了。 另一种常见也是标准方式之一,就是Identity Provider生成SAML Assertion页面,通过HTTP-POST的方式提交到Service Provider。一般来讲SAML Assertion都会经过PKI方式的加密,所以也可以防止中间人攻击。Service Provider通过HTTP协议收到了SAML Assertion,然后构造本地Session。这种方式更有效的解开Identity Provider和Service Provider的耦合。 完整的跨域SSO应用场景: 上述只是一个简单的跨域SSO场景。真正的跨域场景还是要复杂很多。比如Google有自己的identity provider,service provider。但它收购一个不同域名的新公司,这个公司也有自己的identity provider和service provider,这种集成就要复杂一层,但大体流程还是这样的,只不过service provider和identity provider的概念稍微有些改变。双方需要有公认的IDP,而针对于这个IDP,其他的IDP就成了SP。而如果只在自己的域内,自己的IDP还是IDP,SP还是SP。 SSO的其它问题: SSO是个安全问题。安全肯定是第一位的,信息传递时如何加密,如何仿冒,如何防止各种攻击(比如跨站脚本攻击)。还有各种服务器的集成。 [...]