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的实现而言,好像是这样的
- 当有Session启动时,服务器生成一个唯一值,称为SessionID(好像是通过取进程ID的方式取得的)。
- 然后,服务器开辟一块内存,对应于该SessionID。
- 服务器再将该SessionID写入浏览器的cookie(一些在网页的源代码中有所体现)。
- 服务器内有一进程,监视所有Session的活动状况,如果有Session超时或是主动关闭,服务器就释放该内存块。
- 当浏览器连入IIS(服务器)时并请求的ASP(脚本语言)内用到Session时,IIS(服务器)就读浏览器Cookie中的SessionID。
- 然后,服务检查该SessionID所对应的内存是否有效。
- 如果有效,就读出内存中的值。
- 如果无效,就建立新的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作为一个所谓的“开源项目”,仿佛是人人都在为他服务,但是又好象人人都不给他服务。没有一个机构能够真正的去帮助别人熟悉和使用他。
OAuth
OAuth跟OpenID差不多实际不属于SSO范围.是用户身份权限制认证。解决的问题是授权。比如,以前在twitter的应用需要输入用户名和密码,自从用上OAuth以后,就需要一个授权的过程。
OAuth是由Blaine Cook、Chris Messina、Larry Halff 及David Recordon共同发起的,目的在于为API访问授权提供一个开放的标准。OAuth规范的1.0版于2007年12月4日发布。
OAuth流程图
![../_images/OAuth_diagram.png](https://i-blog.csdnimg.cn/blog_migrate/f313f445082fad6700c6b167d529e8c9.png)
- 获取未授权的Request Token(请求令牌);
- 获取用户授权的Request Token(授权令牌);
- 用授权的Request Token换取Access Token(访问令牌);
- 当应用拿到Access Token后,就可以有权访问用户授权的资源了。上述的三个步骤中,分别请求不同及独立的URI地址,且仅能访问一次。
具体每步执行结果如下:
- 使用者(第三方站点)向`OAuth`_服务提供商请求未授权的Request Token。向Request Token URI发起请求,请求需要带上的参数见上图;
- OAuth服务提供商同意使用者的请求,并向其颁发未经用户授权的OAuth_token与对应的OAuth_token_secret,并返回给使用者;
- 使用者向OAuth服务提供商请求用户授权的Request Token,即向User Authorization URI发起请求,请求附带上一步拿到的未授权的token(令牌)与其secret(密钥);
- OAuth服务提供商将引导用户进行授权认证。该过程可能会提示用户,你想将哪些受保护的资源授权给该应用,此步可能会返回授权的Request Token也可能不返回,如Yahoo OAuth就不会返回任何信息给使用者;
- Request Token 授权后,使用者将向Access Token URI发起请求,把上步授权的Request Token换成Access Token;
- OAuth服务提供商同意使用者的请求,并向其颁发Access Token与对应的密钥,最后返回给使用者。
- 使用者以后就可以使用最后获取到的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流程图
![../_images/cas.jpg](https://i-blog.csdnimg.cn/blog_migrate/b9a6277b6d2d931ef4929583dc3536f1.jpeg)