让网站支持OpenID的方法

来源:百度文库 编辑:神马文学网 时间:2024/04/27 17:37:57

让网站支持OpenID的方法

2009年07月22日

.body_content a { text-decoration: underline; }.body_content ul, .body_content ol { margin-top: auto;}.body_content li { margin-top: 1em;}.body_content a img { border-width: 2px; border-style: solid;}.content_container p, .content_container ul, .content_container ol { margin: 1em 0;}.content_container ul, .content_container ol { padding-left: 40px;}.content_container { padding: 1em 0 ;}

对于已经拥有一定数量的注册用户的网站,如何引入对OpenID注册与登录的支持,本教程做了详细的描述。它将告诉你如何让新用户使用OpenID的URL来注册帐号,也让原有的用户轻松绑定他们的OpenID进行登录。

 

概述

首先假定你的网站情况是:

  • 有一个用户数据库
    • 每个用户有一个唯一的内部ID
    • 用户以用户名/Email加上他的密码进行登录
  • 有一个完整的新用户注册和用户信息收集流程
  • 有一个登陆页面供用户进行登录验证身份
    • 用户凭其用户名/Email和密码登陆以后,以其唯一的用户ID号在整个网站通行
  • 有让用户管理其账户信息的页面

如果你的网站不是如上所说的样子,应先将其改成那样。

下面大致说说你需要给你的网站添加的内容:

  1. A 一个新的数据表用于建立OpenID和内部用户ID的对应
    • 这是多对一的关系(每个用户可以绑定多个OpenID,但是一个OpenID只能属于一个用户)。
    • 这个表将是用通过OpenID查询用户的唯一依据,因此必须是一个独立的数据表。
  2. 在新用户注册页面上加上一些OpenID元紊
    • 新用户可以输入他们的OpenID, 通过对应的OpenID提供方验证以后,返回到你的注册页面,选择性提供他们想在你的网站上共享的资料。
  3. 对原有用户需要在登录页面上加上一些OpenID元紊
    • 已经绑定OpenID的用户可以直接输入OpenID,通过对应提供者验证用户身份,并返回到你的网站的验证页面,并通过OpenID和用户ID的对应关系找到对应的帐号,就像他们输入了帐号(e-mail)和密码一样。
  4. 一个OpenID 设置页面供用户浏览、添加、删除他的账号的OpenID绑定。

下面是你将要创建的内容的简要介绍:

  1. 一个OpenID数据表
    • 数据列: (openid_url, user_id). openid_url是字符串,user_id是你当前用户标识身份的内部ID。
    • 把openid_url设为主键(唯一,用来通过OpenID查找用户)
    • 对user_id建立索引(用来对指定帐号列举其绑定的OpenID)
  2. 一个对用户输入的OpenID进行查询并重定向到OpenID提供者的页面
    • 需要检查用户输入的OpenID是否已经进行过绑定
    • 需要重定向到OpenID提供者(使用OpenID库)以便用户进行登录验证(详见后面)
  3. 一个处理OpenID提供者返回信息的页面
    • 需要核实OpenID提供者的响应信息(使用OpenID库)
    • 对于新用户,需要将他们引导到用户注册流程,并预先填充好从OpenID提供者返回的注册信息。还要稍微改一下注册页面让他们不再需要输入密码(因为他们以后将通过OpenID直接登陆)。
    • 对于已经注册的用户,由OpenID查询出内部用户ID完成登录的过程。
  4. 一个用来管理用户的OpenID绑定的页面
    • 可以列出当前登陆帐号的所有绑定OpenID
    • 可以让用户绑定新的OpenID(通过上面所说的流程)
    • 可以让用户解除OpenID的绑定
  5. 在删除用户的代码中加入删除相应OpenID绑定的功能

在正式开干之前你可能需要准备:

  • 一个适合你网站编程语言的OpenID库。由于我们是用C++,所以就采用了libopkele (多谢Michael和他们的Klever团队提供了这个开源的库文件!), 你也可以在这里查到其他语言的库。
  • 一些OpenID的标准图片用于放在你的网站上以提供统一的UI,例如小图标和logo (小图, 标准图, PDF)
  • 一个可以用于测试的OpenID提供者。例如蓝天OpenID,MyOpenID.com, LiveJournal, ClaimID。另外如果你有AOL/AIM账号,也可以直接用http://openid.aol.com/SCREENAME作为你的 OpenID.

实现OpenID用户支持可以给你网站立刻带来如下好处:

  • 超过1.2亿使用OpenID的用户可以更容易、迅速地注册到你的网站,因为他们不再需要另外创建并记住新的帐号和密码。
  • 让你的用户享受到更多的基于OpenID的服务。
  • 以OpenID表明你网站的开放性和领先程度。

当OpenID被越来越广泛的使用之后,你还可以得到以下好处:

  • 可以链接到会员注册的其他网站,让用户无需重新登录。
  • 当用户更改信息时,可以得到最新的更新。
  • 获得可信的信息,如:经过验证的年龄、EMAIL等。

实现的细节

  1. 安装OpenID库
    • 可以在这里查找到各种主流编程语言的OpenID库。
    • 在库的基础上,建立一个与OpenID提供者联系的缓冲,以减少每次验证时重建联系的开销。
  2. 建立一个 OpenID数据表
    • 如以下结构(这是Mysql的,如果你用其他库或者你的用户ID字段名不一样可以自行调整):
      create table user_openids (  openid_url varchar(255) not null,  primary key (openid_url),  user_id int not null,  index (user_id));
    • 只用一个全局OpenID表以方便集中查找用户。(即使是你的用户数据分布在几个不同的库中).
    • 规范的存储OpenID的URL以便查找。(假如下次用户登录时输入的OpenID有点不同,你也可以转成规范的来查找). 大多数OpenID库都有提供规范的函数,简单的说,你要把缺少的http://补上去,把域名转成小写(域名后面的不要转),之类的。例如 "WWW.AOL.COM/myOpenID" 应该存储成:"http://www.aol.com/myOpenID". URL后面多余的/也应该去掉。
    • 如果你有专门的数据访问层代码,可以加上如下的函数。注意,所有用到OpenID的地方在访问数据库之前都应该先进行规范化处理。
      • GetUserId(openid_url)

        select user_id from user_openids where openid_url = openid_url

         

      • GetOpenIDsByUser(user_id)

        select openid_url from user_openids where user_id = user_id

         

      • AttachOpenID(openid_url, user_id)

        insert into user_openids values (openid_url, user_id)

         

      • DetachOpenID(openid_url, user_id)

        delete from user_openids where openid_url = openid_url and user_id = user_id

         

      • DetachOpenIDsByUser(user_id)

        delete from user_openids where user_id = user_id

  3. 注册页面添加OpenID支持
    • 在注册页面上添加一段方便OpenID用户注册。总体来说要达到让使用OpenID的用户一眼就能看出你的网站支持OpenID,而其他用户仍然可以使用原来的注册方式不受影响。可以直接在页面上放一个OpenID输入框或者一个链接指向专门的OpenID输入页面。
    • 要注意让命名和风格都符合OpenID的规范:
      • 把输入框的ID和name属性都设为"openid_url"
      • 添加OpenID的小logo作为输入框的背景,CSS代码如下:
        background: #FFFFFF url('/images/openid-icon-small.gif') no-repeat scroll 0pt 50%;padding-left: 18px;
    • 提供一个关于OpenID是什么以及怎么在你的网站上使用OpenID的简短说明。
    • 把OpenID输入框放在一个form里面,form的action指向你的OpenID输入处理程序。
    • 在用户完成OpenID验证重定向返回你的注册页面时,应该注意:第一,要显示该用户所用的OpenID URL,最好摆在一个OpenID的小LOGO后面以便一眼就能看出。第二,不要再让用户设置登录密码。
    • 下面是一些图例:

  4. 登录页面添加OpenID支持
    • 首先也要考虑好同时照顾使用OpenID的用户和使用传统登录方式用户。
    • 在每一个有传统登录方式的地方都应该加上OpenID的登录方式。
    • 以下图例:

  5. 创建OpenID登录的处理页面
    • 输入的参数最基本的有两个:
      • openid_url: 用户输入的OpenID
      • action_type: 用户的操作类型. 可能是login, complete, attach, list, 和 delete.
    • 完成登录过程
      1. 由openid_url通过前面所说的GetUserId函数查找用户ID.
      2. 如果这个OpenID已经绑定好某个用户ID,先看看这个用户ID是不是当前已经登录到本网站。
        1. 如果这个用户ID并未登录就重定向到OpenID提供者那里进行登录验证。
        2. 如果这个用户ID已经处于登录状态,并且这个OpenID也是他所绑定的,就无需任何操作了。
        3. 如果这个用户ID已经处于登录状态,但这个OpenID不是他所绑定的,提示错误信息。
      3. 如果在数据库中没有找到这个OpenID,引导用户到注册页面。
      4. 把openid_url存放在session中以便用户从OpenID提供者那里验证返回以后提取出来使用。如果你没有用session的话就要用一个数据库来保存。要放在一个用户无法改变的地方,用cookie就不好。

        (要保存openid_url的原因是OpenID允许代理登录。例如我用我的博客URL(http://blog.bluesky.cn)做为我的OpenID,但这个OpenID号其实是真正的OpenID号http://openid.bluesky.cn/bluesky的代理,其登录验证是到OpenID提供者openid.bluesky.cn上去进行的,如果没有事先记录好我的登录的openid_url是http://blog.bluesky.cn的话,那么验证返回以后可能会被误认为是http://openid.bluesky.cn/bluesky。还好大多数OpenID库会做好这个处理,但最好还是在你自己的session保存一个原始的openid_url。这个问题在OpenID 2.0规范中将得到解决)
      5. 向OpenID提供者提交return_to URL以便验证完成以后返回接着进行后续的登录处理。
      6. 对于新注册的用户,要想好需要用户提供哪些信息。多数OpenID提供者支持simple-registration extension, 可以提供常用的几个注册信息,如:full name, e-mail, nickname, gender, date of birth, gender, postal code, country, language, and time zone. 如果你需要这些信息并且用户也愿意通过OpenID提供给你,那么你可以把它们预填写在注册页面的输入框中,省去用户重复输入的操作。如果你的OpenID库不支持simple-registration 参数的话,看看能不能使用自定义的扩展,实在不行的话把这些参数手工加到跳转的URL中也可以。
      7. 在OpenID库中调用 checkid_setup来生成重定向用户到OpenID提供者页面的URL。同时传递规范化的OpenID url和前面所构建的return_to URL。还可以选择你所需要的simple registration项。
      8. 重定向用户到前面生成的OpenID验证的URL。最好用服务端的重定向功能而不是客户端的。
      9. 用户被重定向到OpenID提供者网站以后,如果尚未登录的话先进行登录,然后用户会被询问是否信任你的网站,如果你要求提供simple registration信息的话,用户还可以选择是否提供这些信息给你。当这个步骤完成以后,OpenID提供者会重定向用户回return_to URL,然后你就可以继续完成后续的工作了。

        以下图例:

    • 完成验证以后的后续操作:
      1. 返回的return_to URL带有各种OpenID提供者给回的信息,将其取出。
      2. 取出session中保存的OpenID。
      3. 调用OpenID库中的id_res来验证返回的信息,看用户是否通过验证并提示给用户。
      4. 可选: 在验证成功后,你也可以在你的网站给这个OpenID设置一个永久的cookie,下次这个用户进入网站的时候就可以在OpenID输入框预先填充好这个OpenID了。如果这样做的话,需要确保当用户注销时清除掉这个cookie。
      5. GetUserId函数查询用户ID。如果你不能从数据库中获取,检查用户是不是这会已经登陆了。如果是,执行attach动作绑定OpenID到用户已经存在的帐号。否则,是时候启动注册进程创建一个使用改OpenID的新帐户了。保存OpenID到session,这样账户创建的代码将能确保这个用户已经验证过这个OpenID了。(不要使用存取请求过的OpenID的session变量了,因为用户可以输入任何内容给那个变量)

        然后将用户重定向到注册流程,并填充你获取的简单注册信息(如果有的话),因此你需要想办法把返回的这些注册信息和你网站平常使用的注册信息关联起来。

        • 像上面所描述的一样,注册页面应该非常显著地显示OpenID,并且不要在此要求用户为你的网站输入密码,因为他们已经使用OpenID登陆了。另外,你应该把从OpenID提供者获取的简单注册信息预先填充好。你可以继续要求额外的一些注册信息并且保持你网站当前对信息的要求,比如哪些必填,哪些可选填。(使用OpenID将加快注册速度,但并不是要求你你改变对注册信息的要求直至影响网站的正常行为)最后,你应该提供给已经注册用户绑定OpenId的链接。
        • 当用户完成注册流程,创建了一个新用户帐号,将可以使用AttachOpenID函数来绑定OpenID到新帐号上了。如果你的用户表和OpenID表分布在不同的数据库,不能同步进行访问,可能会导致绑定命令失败,从而导致鼓励帐号存在。这种情况不可能完美地组织,但也是非常罕见地,况且,用户可以重新登陆,你大可以忽视这种情况。
      6. 如果你已被验证的OpenID绑定到了一个已经存在的帐号上,通过传统的方法你也可以正常地登陆网站。如果用户正好用别的帐号登陆,注销掉,以OpenID绑定的帐号登陆。
    • 实现attach功能 (帮助已经注册的用户绑定新的OpenID到账户上):
      1. (这个方法可以看作是complete方法的一部分,因为它发生在用户已经登陆而且已经验证过了一个新的OpenID,所以在调用此方法时需要确保这个用户已经登陆了。)
      2. 用AttachOpenID函数绑定已经验证过的OpenID到登陆的用户账户.
      3. 提示用户这个OpenID已经绑定成功,今后可以它直接登陆。接下来可以考虑调用list方法,这样用户就能从列表中看到这个OpenID了.

        图例:

    • 实现 list 功能 (用来展示用户账户上绑定的所有OpenID):
      1. 需要用户登陆.
      2. 用GetOpenIDsByUser函数获取绑定的OpenID列表
      3. 对应每个绑定的OpenID提供链接用来解除绑定,用户点击后将传入openid_url参数执行delete的动作。
      4. 提供增加OpenID的输入框或链接。这将把用户带入到登陆和绑定流程,最后将返回这个列表页面。
      5. 如果你的网站已经有一般设置页面,你应该提供类似“管理你的OpenID”的链接到列表页面。

        图例:

    • 实现删除功能 (用来从用户账户中解除一个OpenID):
      1. 需要用户已经登陆。
      2. 可选:检查这个OpenID是不是用户最后一个在你的网站的身份凭证。如果用户没有设置你网站的密码而且这是他唯一绑定到他账户的OpenID,删除这个OpenID将会使用户完全脱离这个账户。如果没有好的办法是用户能恢复他的帐号,而且用户试图删除这个最后的身份凭证,那么就显示一条错误信息吧——“你不能删除你帐号上的最后一个OpenID,这样你将没办法再登陆本站。你可以先绑定另一个OpenID或者创建在本站的密码”。
      3. 传递openid_url参数给DetachOpenID函数,正常的话,就可以解除对它的绑定了。如果提供的OpenID并未绑定到用户的账户,你可以提示错误或者无视它即可。
      4. 显示确认信息,表明这个OpenID已经被解除绑定,不能在你的网站继续使用。告诉用户如果他想再次绑定这个OpenID,则需要通过正常的验证过程重新绑定。然后可以考虑重新定向到OpenID列表页面,用户就能看到列表的更新情况。

        图例:

    • 如果要删除一个用户帐号,就需要删除这个帐号绑定的所有OpenID
      1. 如果你的网站支持用户删除账户,删除该账户绑定的任何OpenID也相当重要,因为这样,这些OpenID才有机会绑定到其他账户上。你可以在删除用户账户的时候调用DetachOpenIDsByUser函数来实现这个操作。