Rainfall’s CodeLife

C/C++/C#/VB/JavaScript/Python/XML

 

网站认证方法 December 22, 2006

Filed under: Miscellaneous — Rainfall @ 6:52 am

参考资料:
http://www.yupoo.com/apidoc/
http://code.google.com/apis/accounts/Authentication.html

网站的登录认证方式从单一网站到认证系统基本可以分为三种形式:

  • 单网站单服务器登录
  • 单网站多服务器登录
  • 以及多网站多服务器认证

传统网站由于其体系相对的封闭特性,通常都只采用前两种登录方式,但随着Web2.0对网站的开发性要求,很久以来本地软件就已经成熟的API体系也逐渐被网站应用采用。

而网站应用最重要解决的问题就是安全认证,在保证网站内部关键数据不外泄的前提下提供信息。认证登陆则是解决这个问题的门锁。

★ 单网站单服务器登录

这是最简单的认证形态,登录信息不存在共享,只被一个应用服务器使用。因此,无论采用何种方式记录登录信息都可以,session数据可以放在服务器内存中,或者服务器数据库。用户在浏览器中输入帐号密码,发送到服务器后,由服务端通过用户数据库进行认证后将用户标识记录在服务器内的SessionData中。而客户端只记录Session的标识。

Account&Password <==|==>Session<==|==>KeyData
         (Client)                         (Server)               (BackDB)

用数据库记录Session数据有两个目的,其一是为了实现永久性登录,需要在Client端利用Cookie记录SessionID,以便服务器恢复登录状态(Session)。所以对于CookieDisable的浏览器是无法实现永久登录的。这就需要在数据库中保留Session数据。Django的Session数据库字段非常简单(SessionID,Data,Expire),通常Session数据都很简单,只记录标识,不记录大数据内容。

数据库维持Session另一个原因就是下面的多服务器登录。

★ 单网站多服务器登录

由于内存数据无法跨进程共享,更不可能做到跨服务器共享。但是现在大部分网站都由多台主机同时提供服务,用户在前后多个页面时,很有可能是有分别不同的主机提供的内容。如果内容和具体用户无关还好,但如果提供的个性化页面情况就不同了,这些服务器必须保存状态数据。

现在的互联网应用基本遵从“无状态服务”架构,这也是现在互联网能够服务海量服务请求的一个重要前提,所以SessionData应该尽量简单,其根本目的就是为了标识,而不是存储。
现在越来越多的网站都不再遵守这个框架原则,这主要是现在互联网对个性化服务的追求带来的变化,因此在设计具体网站时,要认真把握好有无状态的平衡。

状态数据必须利用数据库实现跨服务器访问,通常内容服务器只需要读取Session数据,而需专门的认证服务器来创建(或恢复)登录信息到Session中。

Account@Psw <==|==> LoginServer <==|==> UserDatabase
                        |
                     Session
                        |
    Browser <==|==> ContentServer(s) <==|==> ContentDatabase

由于大型网站对登录的需求多种多样,主要是登录完成后的处理方式的不同:

A)单独登录页面

这种方式需要在登录成功后进行重定向,比如网站首页,登录前的页面。最简单的方式就是通过Url传递返回地址,如:

http://somesite.com/login/?back=http://somesite.com/index

前段时间微软发布了一种“PageFunction”概念,这样就可以把登录页面作为一个函数来调用,这样可以想函数调用一样更方便的解决返回地址问题。

Caller       Page Func
——       ———
Call page =>
             login page
Call page <=

B)嵌入式登录页面

在网站中对于登录需求有两点很强烈:第一就是返回登录前地点,第二就是随时随处登录。嵌入式登录页面可以很好的解决这个问题,甚至可以做到登录时不跳转当前页面。

+————+——————–+
|            | login page(frame)  |
|            +——————–+
|             内容页面             |
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|

通过Frame嵌入登录服务器提供的登录页面,登录页面通过对当前用户状态的判断,决定显示登录内容还是注销、用户信息。而内容页面可以通过Session或DOM对登录进行控制。这种方式其实本质就是利用frame解决了前种方案的跳转问题,而且实行方式不需要内容页面做特殊处理,甚至可以通过master page将登录小页面实现到所有内容页面上,解决随时随处登录的问题。

但是随着网络应用的复杂度增加,内容服务器不可能都用同一个平台开发,甚至不可能运行在一个局域网内,更谈不上访问Session数据库。解决这个问题,就必须采用开放式的认证系统。

★ 多网站多服务器认证

对于不能运行在同一个局域网的服务器组,我们可以认为这些服务器是互不信任,甚至真的就是第三方的服务器,比如我要做一个专题图片展览,而应用的图片都来自于Flickr或者Yupoo,这就需要获取Flickr和Yupoo的认证。当然,Flickr不可能公开他的UserDatabase,其实我也不需要,我只要能让Flickr知道我能访问权限即可。

Client     专题展览应用      Flickr
——     ———-      ——
  –图片请求–>    —请求登录—>
  <——————登录页面—
  –输入账户密码—————->
  <–SessionId–  <–认证标识—
  –SessionId–>  —认证标识–>
  <——————图片数据—

从这个交互图,我们可以看出“认证标识”其实可以认为就是Flickr的SessionId,但实际并不是这么简单。原因有几个:

A)账户和密码只能由Client直接在Flickr上输入(不能让专题应用知道用户隐私)

B)flickr的SessionId只能保留在Client中,专题应用是拿不到的

C)不可能应用每做一次flickr调用之前都让用户输入密码

因此上图中的认证标识必然是一个“登录用户标识”和“应用标识”的对应体,而且是稳定存在的。因此登录流程改变成:

Client         应用          Flickr
——         —          ——
   –登录–>     –登录(+key)–>
  <–SessionId-  <–Token—–(根据账户,应用Key创建Token)

key就是一个第三方应用的标识,而Token则对应了唯一的UserAccount+AppKey。Token是一个比session更持久的认证标识,为了使过程更可控,这个过程会优化为:

Client         应用          Flickr
——         —          ——
   –登录–>      –请求frob—>
                 <–frob(一段时间内有效)–
                 –登录(+key+frob)–>
                 <–frob—–(根据账户,应用Key创建临时Token)
                 –获取token—->
<–SessionId-    <–Token—-(将临时Token转化为正式Token)

frob就是一个请求token的临时入场券,token生成后必须在要求的时间内确认获取才会生效。

Token是一个很可怕的东西,他会通过Http的Uri或者Form明文传递,而且始终有效,一旦被别人掌握,这实在太可怕了!解决方法很简单,只需为每个创建的AppKey都同时随机创建一个ShareSecret,这个secret只被“应用”和“flickr”掌握,需要传递Token的时候,只需要把secret和调用参数合在一起,利用md5等不可逆算法计算出“签名”一并发送即可。

 

WordPress database error: [Table 'duanyuluocode.wp_comments' doesn't exist]
SELECT * FROM wp_comments WHERE comment_post_ID = '13' AND comment_approved = '1' ORDER BY comment_date

Leave a Reply