`
jxh118
  • 浏览: 122768 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

如何让你的网站也支持OpenID(转载)

阅读更多

这是一个非常详细的教程,它将指导那些已经拥有了用户的网站,如何来一步一步实现对OpenID的支持。它将解释如何让新用户使用OpenID的URL来注册帐号,并让原有用户轻松绑定他们的OpenID。这个教程看起来有些长,因为我的目的是希望你不用做任何思考,在看完文章的时候就可以轻松搞定这些事情。

概况

首先我假定你的网站已经具备了以下的条件:
1.一个用户信息数据库;

  • 每个用户有唯一的内部ID,用户通过他们的帐号(e-mail)和密码登陆。

2.完善的注册新用户和收集基本信息的流程;
3.有验证用户的登陆页面;

  • 通过用户的帐号(e-mail)和密码验证用户身份,并在网站其他地方依赖用户ID作为用户身份的象征。

4.有专门的页面用来管理账户信息。

如果你的网站不像以上所说的,你首先应该将它改造成这样,虽然某些细节可能有些出入。

下面是需要给你的网站增加的大体内容:
1.一个存储OpenID和用户的内部ID关系的数据表;

  • 它们之间是多对一的关系(每个用户可以绑定多个OpenID,但是一个OpenID只能属于一个用户)。
  • 这个表将用来通过OpenID查询所有的用户,因此必须是单独的一个数据表。

2.需要在注册界面上增加一些有关OpenID的内容;

  • 新用户将输入他们的OpenID,通过其对应的提供者来验证,并返回到你的注册页面,选择性提供他们想在你的网站上共享的资料。

3.对现有用户,也需要在登陆页面增加一点内容;

  • 已经绑定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到他们的账户上(如果是他们是第一次使用它)。

4、用来管理用户绑定的OpenID的动态页面

  • 能获取和浏览所有绑定到当前登陆帐号的所有OpenID。
  • 能让用户绑定新的OpenID。
  • 能让用户删除已经绑定过的OpenID。

5.在删除用户的代码中增加删除该用户绑定过的OpenID的功能。

在正式开始之前你可能需要下面的资源:
1.选择一种程序语言的OpenID用户库,点击查看各种语言的用户库。
2.放置在你的网站界面的标准OpenID图形。比如小图标和logo(正常PDF)。
3.利用一些OpenID提供者来进行测试。比如MyOpenID.comLiveJournal、和ClaimID。另外,如果你有AOL/AIM的帐号,你可以用http://openid.aol.com/USERNAME作为一个OpenID(USERNAME代表你的帐号)。

实现OpenID用户支持能立刻享受以下这些好处:
1.1.2亿使用OpenID的用户将更容易、迅速地注册到你的网站,因为他们不再需要创建并记住心得帐号和密码。
2.当你开始收集你用户的OpenID时,你网站的用户将能更容易地享受到很多基于OpenID的服务。
3.通过支持这个举足轻重的在线身份的开放标准,你将证明你的想法和对会员的承诺。

另外,随着对OpenID支持的不断增多,你将可能享受到更多的好处:
1.自动链接到会员在别的网站的帐号,从而共享信息给Mashup,避免用户在不同的地方多次输入重复的信息。
2.当会员在别的网站更改信息时,你能更轻松地获取到他们的最新动态。
3.接受别的网站或服务提供的可信服务,比如年龄确认,e-mail认证,群组会员资格验证等等

实现细节
1.安装一个OpenID用户库

  • 目前已经有很多流行编程语言的OpenID库,它们替你解决了绝大部分的负担。
  • 在库的基础上,你需要建立和提供者网站之间的联系,实质上,就是建立把服务和处理器处理成连接字符串。你至少需要把这种联系存储在session中,用来验证一个OpenID的授权,但比较完美的情况还是你长期存储他们,这样就不用每次重定向到OpenID提供者时都重新建立他们之间的联系。你可以用 memcached、数据库或者其他你能访问到的存储介质。

2.创建一个OpenID数据表

  • 你可以使用下面的schema:
  • 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后面多余的/也去掉。
  • 如果你经常使用数据访问层的代码,你应该把下面的函数提供给程序(在每个函数下边我都提供了对应的sql语句)。还要提醒一下,所有用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
2.添加OpenID的内容到注册页面

  • 添加内容使得OpenID用户可以通过OpenID登陆。这部分UI的目标是是OpenID用户很容易识别你的网站支持OpenID,但非OpenID用户又不会因此感到迷惑。你可以添加一个OpenID输入框或者一个到可以输入OpenID的页面的链接。
  • 无论你放到哪,你都必须使输入框符合OpenID的命名规范:
  • 使用“openid_url”作为文本框的id和name属性(这将能使插件更加容易识别和处理来自不同网站的OpenID的输入框)。
  • 添加小OpenID logo作为输入框的北京,使用类似的css样式:
    background: #FFFFFF url('/images/openid-icon-small.gif') no-repeat scroll 0pt 50%;
    padding-left: 18px;
  • 如果提供对OpenID的介绍以及在你的网站如何使用它的简短说明,将会是个不错的注意,这样能吸引那些好奇的人过来一探究竟。
  • 将输入框放入到一个form中,设置form的action为处理OpenID的页面,接下来我们就着手建立这样的页面。
  • 在提供了OpenID并在OpenID提供者登陆以后,用户将返回到注册页面,这里有两个需要注意的地方。第一,你应该显示该用户注册的OpenID,把小OpenID logo放在后面会更好。第二,你不应该再次要求用户输入在你的网站的密码,因为他们将通过OpenID直接登陆。所以需要吧密码框隐藏起来,并确保你的代码能允许这样(如果你的程序一定要求要有密码的话,你可以生成一些随机字符串,只不过不让用户看到而已)。请注意:也可以在帐户设置页面让用户输入一个你网站的密码,不过需要注意使用OpenID的最大好处是用户不用再维护他们在各个网站不同的注册信息。

3.添加OpenID相关内容到登陆页面

  • 添加OpenID用户登陆的内容到登陆页面。这对已经注册并绑定了OpenID的用户和用OpenID注册的新用户都是有用的。想注册页面一样,UI的设计目标是需要保持非OpenID用户和OpenID用户之间的平衡。你应该使OpenID输入框的命名和样式和注册页面保持一致。包围输入框的form也应该只想你将创建的动态页面。
  • 在网站其他任何有传统登陆方式的地方,你都应该增加OpenID的登陆方式。

4.创建一个OpenID登陆的动态页面

  • 必须提供两个基本的访问参数给动态页面
  • openid_url:用户指定的OpenID,包括注册、登陆、绑定等。
  • action_type:用户要采用的操作类型。这个参数的只有可能是login、complete、attach、list和delete。(如果你用Rails或者类似的体系,这些可能是一个控制器方法或者url本身的一部分)
  • 实现login动作(这是在注册和登陆流程里边都要提交到的地方)
  1. 用上文提到的GetUserId函数获取openid_url。
  2. 如果OpenID已经被你网站的用户绑定过了,检查这个用户是不是已经在你的网站登陆了。
  1. 如果这个用户还没有登陆,则用户是试图用这个帐号登陆,所以需要准备重定向到对应的OpenID提供者,但是需要设置一个标记表明不是用来注册。
  2. 如果用户已经登陆了,而且这个OpenID属于用户(也就是说,这个OpenID的URL已经关联到这个登陆用户的user_id),你就不需要做任何事情(这个用户已经登陆而且已经绑定了这个OpenID,所以这是相当于没操作),这是一个特殊情况。
  3. 如果这个用户已经登陆了,但OpenID属于另一个用户,则提示这个账户已经被另外的用户绑定过了。你同事可以提供注销和再试一次的选项。这是另一种特殊情况。

如果这个OpenID还没有存在你的数据库中,那么这个用户是尝试用它注册新帐户,把页面重定向到OpenID提供者并请求注册信息即可。保存openid_url在session,因为当OpenID提供者返回时有可能并不返回这个值给你。如果你的网站不支持session,你可以使用数据库,但最重要的是这个保存的地方不能收到用户的干预(比如cookie或者可以被用户改变或“杜撰”内容的地方)。(需要你保存请求的OpenID是因为OpenID允许用户使用其他网站的代理。举例来说,如果我视图用OpenID josephsmarr.com来登陆,我可能会用选择另一个OpenID jsmarr.myopenid.com作为代理,当提供者验证完毕返回时,你需要记住我是想用josephsmarr.com登陆而不是jsmarr.myopenid.com。幸运的是,大多数OpenID库已经处理这个问题了,但是你还是需要保存原始请求的OpenID在session里边。这种问题有可能在OpenID2.0中得以解决。)用户验证通过后的返回地址参数return_to需要由这个动态页面提供,这个页面将用来处理complete动作。如果你判断用户准备注册一个新帐户,就需要确定他提供哪些额外的注册信息。大部分的OpenID提供者都支持这些简单注册内容,这些信息是一些通用的内容,包括姓名、email、昵称、性别、生日、邮政编码、国家、语言以及时区,你可以随取所需,从而减少注册流程的时间以及一些额外的负担。如果你的OpenID用户库并不支持对简单注册参数的请求,可以看看库是不是提供对扩展的支持,即使是最坏的情况,你也可以在重定向之前添加请求参数到转发地址。调用OpenID库中checkid_setup函数产生OpenID提供者的地址。需要传递给OpenID提供者用户名和第5步创建的返回地址,另外,还有你想获取的简单注册信息的相关参数。你可能需要获取和处理这个函数的某些错误,但如果假定一切OK的话,你将得到需要重定向的地址。通过发出服务器端的重定向应答,让动态页面重定向到上面获取的地址。用户将会被重定向到OpenID提供者的网站,他们需要登陆(除非已经登陆过了),然后需要决定是否新人你的网站,如果有注册信息请求的话,也需要决定共享哪些信息给你。如果他们完成了这些过程,OpenID提供者将会把页面转到你提供的return_to所指向的URL地址,然后你将启用你的complete动作完成整个处理流程了。实现complete动作(当用户已经登陆OpenID提供者的网站并返回的时候)

  1. 当OpenID提供者返回到你的return_to地址时,他们会在地址上添加一些用来验证用户授权信息的请求参数。通过你使用的OpenID库,你可能需要收集这些信息为指定的数据结构,用来通过验证函数,也有可能它自己就帮你做好这些事情了。
  2. 从session中获取用户最初请求的OpenID。
  3. 调用OpenID库中的id_res来验证你发给OpenID提供者的授权数据。传给用户请求的原始OpenID,以及一些必要的请求参数。这个函数将检查是不是一切都有效。如果它返回错误信息,给用户提示适当的一些信息;否则你就可以正式确认这个用户的合法性了。
  4. 在验证成功后,你也可以在你的网站给这个OpenID设置一个永久的cookie,下次这个用户进入网站的时候就可以在OpenID输入框预先填充好这个OpenID了。如果这样做的话,需要确保当用户注销时清除掉这个cookie。
  5. 用GetUserId函数重新获取验证过的OpenID。如果你不能从数据库中获取,检查用户是不是这会已经登陆了。如果是,执行attach动作绑定OpenID到用户已经存在的帐号。否则,是时候启动注册进程创建一个使用改OpenID的新帐户了。保存OpenID到session,这样账户创建的代码将能确保这个用户已经验证过这个OpenID了。(不要使用存取请求过的OpenID的session变量了,因为用户可以输入任何内容给那个变量)然后将用户重定向到注册流程,并填充你获取的简单注册信息(如果有的话),因此你需要想办法把返回的这些注册信息和你网站平常使用的注册信息关联起来。
  • 像上面所描述的一样,注册页面应该非常显著地显示OpenID,并且不要在此要求用户为你的网站输入密码,因为他们已经使用OpenID登陆了。另外,你应该把从OpenID提供者获取的简单注册信息预先填充好。你可以继续要求额外的一些注册信息并且保持你网站当前对信息的要求,比如哪些必填,哪些可选填。(使用OpenID将加快注册速度,但并不是要求你你改变对注册信息的要求直至影响网站的正常行为)最后,你应该提供给已经注册用户绑定OpenId的链接。
  • 当用户完成注册流程,创建了一个新用户帐号,将可以使用AttachOpenID函数来绑定OpenID到新帐号上了。如果你的用户表和OpenID表分布在不同的数据库,不能同步进行访问,可能会导致绑定命令失败,从而导致鼓励帐号存在。这种情况不可能完美地组织,但也是非常罕见地,况且,用户可以重新登陆,你大可以忽视这种情况。

如果你已被验证的OpenID绑定到了一个已经存在的帐号上,通过传统的方法你也可以正常地登陆网站。如果用户正好用别的帐号登陆,注销掉,以OpenID绑定的帐号登陆。

  • 实现attach方法(帮助已经注册的用户绑定新的OpenID到账户上)
这个方法可以看作是complete方法的一部分,因为它发生在用户已经登陆而且已经验证过了一个新的OpenID,所以在调用此方法时需要确保这个用户已经登陆了。
  1. 用AttachOpenID函数绑定已经验证过的OpenID到登陆的用户账户。
  2. 提示用户这个OpenID已经版定成功,今后可以它直接登陆。接下来可以考虑调用list方法,这样用户就能从列表中看到这个OpenID了。
  • 实现list方法(用来展示用户账户上绑定的所有OpenID)
  1. 需要用户登陆。
  2. 用GetOpenIDsByUser函数获取绑定的OpenID列表。
  3. 对应每个绑定的OpenID提供链接用来解除绑定,用户点击后将传入openid_url参数执行delete的动作。
  4. 提供增加OpenID的输入框或链接。这将把用户带入到登陆和绑定流程,最后将返回这个列表页面。
  5. 如果你的网站已经有一般设置页面,你应该提供类似“管理你的OpenID”的链接到列表页面。

实现delete方法(用来从用户账户中解除一个OpenID)

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

如果要删除一个用户帐号,就需要删除这个帐号绑定的所有OpenID。

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

呵呵,你终于做完了!
如果你现在做完这些了,那么恭喜你了,你现在已经拥有让你的网站实现对OpenID支持的十八般武艺。上面的步骤已经非常彻底和完善,但是如果在实现的时候遵循下面的规则,将对你更加有帮助:

  • 无论何时将OpenID显示在页面上,把OpenID的小图标显示在前面,使其意义非常明显。
  • 一般来说,在你将OpenID公之于众的时候,需要征求用户的同意。也许有得用户愿意把它作为一个公用的身份,但你最后还是假定他们只是愿意作为一个私有的象征。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics