Cookie + Session + OAuth + SSO =================================== .. contents:: Introduction ---------------------------- 周五的技术沙龙,Rain和Joey讲了关于Cookie + Session + `OAuth`_ + SSO的一些知识。觉得很是有用,所以又从网上翻资料出来,做个记录。 HTTP协议 ---------------------------- HTTP虽然是基于TCP/IP,但是HTTP本身却是无状态协议。每次HTTP简单的请求和响应是独立事件,事件之间没有状态的联系。而TCP/IP在实现的时候,需要两端维持一个协议状态机,并根据网络事件进行状态的跃迁。 Cookie ---------------------------- 在BS开发中,Cookie和Session是很重要的两个概念。 Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递。用户每次访问站点时,Web 应用程序都可以读取 Cookie 包含的信息。 Cookie 的基本工作原理如果用户再次访问站点上的页面,当该用户输入 URL www.abc.com 时,浏览器就会在本地硬盘上查找与该 URL 相关联的 Cookie。如果该 Cookie 存在,浏览器就将它与页面请求一起发送到您的站点。 Cookie中包含用户名和密码,再加上一些信息以后,进行MD5或其他加密方式加密后生成的字符串。 Session ---------------------------- session是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过SessionID来区分不同的客户,session是以Cookie或URL重写为基础。默认使用Cookie来实现,系统会创造一个名为JSESSIONID的输出Cookie,或称为"Session Cookie". Session的工作原理 ---------------------------- 就session的实现而言,好像是这样的 1. 当有Session启动时,服务器生成一个唯一值,称为SessionID(好像是通过取进程ID的方式取得的)。 2. 然后,服务器开辟一块内存,对应于该SessionID。 3. 服务器再将该SessionID写入浏览器的cookie(一些在网页的源代码中有所体现)。 4. 服务器内有一进程,监视所有Session的活动状况,如果有Session超时或是主动关闭,服务器就释放该内存块。 5. 当浏览器连入IIS(服务器)时并请求的ASP(脚本语言)内用到Session时,IIS(服务器)就读浏览器Cookie中的SessionID。 6. 然后,服务检查该SessionID所对应的内存是否有效。 7. 如果有效,就读出内存中的值。 8. 如果无效,就建立新的Session。 Cookie和Session的安全性 ---------------------------- 相比起Cookie,session 是存储在服务器端的会话,相对安全,并且不像 Cookie 那样有存储长度限制。 由于 Session是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容。实际上在服务器端的 Session 文件,PHP 自动修改 session 文件的权限,只保留了系统读和写权限,而且不能通过 ftp 修改,所以安全得多。 对于 Cookie 来说,假设我们要验证用户是否登陆,就必须在 Cookie 中保存用户名和密码(可能是 md5 加密后字符串),并在每次请求页面的时候进行验证。如果用户名和密码存储在数据库,每次都要执行一次数据库查询,给数据库造成多余的负担。因为我们并不能只做一次验证。为什么呢?因为客户端 Cookie 中的信息是有可能被修改的。假如你存储 $admin 变量来表示用户是否登陆,$admin 为 true 的时候表示登陆,为 false 的时候表示未登录,在第一次通过验证后将 $admin 等于 true 存储在 Cookie,下次就不用验证了,这样对么?错了,假如有人伪造一个值为 true 的 $admin 变量那不是就立即取的了管理权限么?非常的不安全。 而 Session 就不同了,Session 是存储在服务器端的,远程用户没办法修改 session 文件的内容,因此我们可以单纯存储一个 $admin 变量来判断是否登陆,首次验证通过后设置 $admin 值为 true,以后判断该值是否为 true,假如不是,转入登陆界面,这样就可以减少很多数据库操作了。而且可以减少每次为了验证 Cookie 而传递密码的不安全性了(session 验证只需要传递一次,假如你没有使用 SSL 安全协议的话)。即使密码进行了 md5 加密,也是很容易被截获的。 OpenID_ ---------------------------- \ OpenID_\ 实际上不属于SSO, 只是一种身份的认证而已。解决的问题是\ **你是谁**\ 。 \ OpenID_\ 挺NB的,拥有众多大腕粉丝, 例如GOOGLE、YAHOO、Facebook,希望别人的系统使用它们的帐号登陆。他们希望一种足够简单的WEB SSO规范,于是选择一种草根网络协议\ OpenID_\ 。\ OpenID_\ ,名字取得好,顾名思义,一看就知道它是干嘛的。国内也有它的Fans,例如豆瓣网。OpenID的确足够简单,但是协议本身是不完善,可能需要一些补充协议才能够满足业务需求。例如GOOGLE采用\ OpenID_\ + \ OAuth_\ 。目前支持\ OpenID_\ 有Yahoo、Google、Windows Live,还有号称要支持OpenID的Facebook。目前Yahoo和Google宣称对OpenID的支持,但是其实是\ **有限制的**\ ,Yahoo的\ OpenID_\ 只有少数合作伙伴才能获得其属性,Google也只有在其Google Apps中才能获得账号的Attribute。用户账号毕竟是一个互联网公司的最宝贵资源,希望他们完全分享账号是不可能的。\ OpenID_\ 作为一个所谓的“开源项目”,仿佛是人人都在为他服务,但是又好象人人都不给他服务。没有一个机构能够真正的去帮助别人熟悉和使用他。 .. _OpenID: http://OpenID.net/ .. _OAuth: http://OAuth.net/ OAuth_ ---------------------------- \ OAuth_\ 跟\ OpenID_\ 差不多实际不属于SSO范围.是用户身份权限制认证。解决的问题是\ **授权**\ 。比如,以前在twitter的应用需要输入用户名和密码,自从用上OAuth以后,就需要一个授权的过程。 \ OAuth_\ 是由Blaine Cook、Chris Messina、Larry Halff 及David Recordon共同发起的,目的在于为API访问授权提供一个开放的标准。\ OAuth_\ 规范的1.0版于2007年12月4日发布。 OAuth流程图 ---------------------------- .. image:: image/OAuth_diagram.png - 获取未授权的Request Token(请求令牌); - 获取用户授权的Request Token(授权令牌); - 用授权的Request Token换取Access Token(访问令牌); - 当应用拿到Access Token后,就可以有权访问用户授权的资源了。上述的三个步骤中,分别请求不同及独立的URI地址,且仅能访问一次。 具体每步执行结果如下: A. 使用者(第三方站点)向`OAuth`_服务提供商请求未授权的Request Token。向Request Token URI发起请求,请求需要带上的参数见上图; B. OAuth服务提供商同意使用者的请求,并向其颁发未经用户授权的OAuth_token与对应的OAuth_token_secret,并返回给使用者; C. 使用者向OAuth服务提供商请求用户授权的Request Token,即向User Authorization URI发起请求,请求附带上一步拿到的未授权的token(令牌)与其secret(密钥); D. OAuth服务提供商将引导用户进行授权认证。该过程可能会提示用户,你想将哪些受保护的资源授权给该应用,此步可能会返回授权的Request Token也可能不返回,如Yahoo OAuth就不会返回任何信息给使用者; E. Request Token 授权后,使用者将向Access Token URI发起请求,把上步授权的Request Token换成Access Token; F. OAuth服务提供商同意使用者的请求,并向其颁发Access Token与对应的密钥,最后返回给使用者。 G. 使用者以后就可以使用最后获取到的Access Token来访问用户授权的资源。 从上述的步骤中可以看出,用户始终没有将其用户名与密码等信息提供给使用者(第三方站点),从而更安全。 SSO ---------------------------- 单点登录(Single Sign On , 简称 SSO ) - SessionID的局限性在于sevice,由于需要在service的上面,但是当service有多个instance并且instance之间不能够共享sessionID的时候,就会导致问题。比如,当某个instance挂掉以后,在该instance上面的用户会话将不能够保存并继续。 - Cookie可以解决以上跨service instance的问题。Cookie是基于DNS domain在进行加密的,能够解决的是在该域名下面所有服务器的会话问题。可以通过memcached来解决Cookie校验的问题。Cookie的局限性: 在于不同domain之间的共享。 - SSO 即为了解决跨Domain之间的用户校验的问题。 SSO流程图 .. image:: image/cas.jpg Reference --------------------------------- #. http://blog.csdn.net/hongxing4hao/archive/2007/01/24/1492627.aspx #. http://blog.csdn.net/yanbei0391/archive/2010/12/29/6105967.aspx #. http://baike.baidu.com/view/25258.htm #. http://blog.chinaunix.net/space.php?uid=1760882&do=blog&id=93117 #. http://www.douban.com/service/apidoc/auth #. http://huoding.com/2010/10/10/8 #. http://wiki.dianboom.com/index.php/OAuth%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6 #. http://wiki.dianboom.com/images/0/0b/OAuth_diagram.png #. http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/index.html