标题：OpenID
定义
OpenID 是一个以用户为中心的数字身份识别框架，它具有开放、分散、  
自由等特性。
OpenID 的创建基于这样一个概念：我们可以通过 URI （又叫 URL 或网站地址）来认证一个网站的唯一身份，同理，我们也可以通过这种方式来作为用户的身份认证。由于URI 是整个网络世界的核心，它为基于URI的用户身份认证提供了广泛的、坚实的基础。
OpenID 系统的第一部分是身份验证，即如何通过 URI 来认证用户身份。目前的网站都是依靠用户名和密码来登录认证，这就意味着大家在每个网站都需要注册用户名和密码，即便你使用的是同样的密码。如果使用 OpenID （参见规范），你的网站地址（URI）就是你的用户名，而你的密码安全的存储在一个 OpenID 服务网站上（你可以自己建立一个 OpenID 服务网站，也可以选择一个可信任的 OpenID 服务网站来完成注册）。
与OpenID同属性的身份识别服务商还有ⅥeID,ClaimID,CardSpace,Rapleaf,Trufina ID Card等，其中ⅥeID通用账户的应用最为广泛。
优势
登录一个支持 OpenID 的网站非常简单（即便你是第一次访问这个网站也是一样）。只需要输入你注册好的 OpenID 用户名，然后你登录的网站会跳转到你的 OpenID 服务网站，在你的 OpenID 服务网站输入密码（或者其它需要填写的信息）验证通过后，你会回到登录的网站并且已经成功登录。OpenID 系统可以应用于所有需要身份验证的地方，既可以应用于单点登录系统，也可以用于共享敏感数据时的身份认证。
除了一处注册，到处通行以外，OpenID 给所有支持 OpenID 的网站带来了价值－－共享用户资源。用户可以清楚的控制哪些信息可以被共享，例如姓名、地址、电话号码等。
今天，OpenID 作为以用户为中心的身份验证系统已经为数百万的用户提供了服务。在“I Want My OpenID Bounty” 项目的推动下，许多开源项目都迅速的加入了对 OpenID 的支持。
拥有者
没有人拥有它。从字面上就可以看出因为其是“开放的地址”，所以任何人都不能将它用于商业用途。OpenID 按照最大自由方式授权，使用它不需要任何费用任何注册或者许可证。
参与方式
邮件方式通过订阅邮件列表，你能最快最方便的了解 OpenID 的最新进展。你也可以去看看正在孵化中的 OpenID 的参考实现——Heraldry
国内支持openid网站国内支持openid网站：
www.onedoor.cn
openid.cn-功能已失效
www.xinmimi.com -功能已失效
www.yupoo.com - 不再支持
http://show.99shop.org - 不再支持
OpenID协议综述
OpenID协议非常易于扩展，下面的图表展示了OpenID2.0草案的基本工作流程。它展示了在终端用户、Relying Party站点（一个示例站点）和OpenID服务提供者之间的交互过程（最常见的认证流程）。
用户登入外部站点的过程主要分为以下七个步骤：
1.请求用户标识此步骤非常简单：用户提供一个字符串（以URL或者XRI格式）给外部站点，使后者能够识别用户。
⒈外部站点请求用户发送标识。通常使用带有Open图标的文本输入框、用于提交信息的按钮组成的form来完成此功能。为了方便起见，文本输入框的name属性应为openid_identifier，这样以便浏览器自动将其识别为一个OpenID登录form。
⒉用户输入标识，标识可能采用下面的形式：
? URI/URL （通过http或者https)
? XRI。XRI是一种广义的、分散式的URI。它能用于任何使用URI的地方。XRI主要采用以下形式：xri://authority/path?query#fragment。了解更多关于XRI的信息请看：XRI语法规范。
用户标识类似这个样子：http://myname.myhost.com/。外部站点经常将OpenID logo放置到其登录form上，这样可以使你很快地辨别出是否使用OpenID。
用户在点击位于外部站点登录页面上的“Login”按钮后便启动了认证过程。
2.“标准化”⒉“标准化”： Relying Party站点整理用户标识
用户输入了标识后，此标识便由外部站点进行整理（标准化）。由于标识可能使用XRI或者URI格式，因此整理的过程非常复杂：
⒈如果标识以xri://、xri://$ip或者xri://$dns*开头，那么我们要去掉这些头部标记。
⒉如果余下字符串中的第一个字符是XRI的全局上下文符号（=、@、+、 $、！），那么此字符串为标准的XRI标识。否则，将被视为HTTP URL（如果http/https前缀没有定义，我们需要为其添加上http://）。当然，URL必须遵守URL命名规范。最终获得的URL就是一个标准的URL标识。
下面是一些示例：
下面的流程图描绘了标准化处理过程：
3.“发现”⒊“发现”： Relying Party站点查询与OpenID服务器进行通讯的方式
外部站点使用标准化的标识来查询用于发起请求所必须的信息。对于“发现”阶段来讲，其使用的解析协议和获取的结果文档都取决于在标准化阶段决定的标识类型。这正是OpenID2.0规范的特殊之处。
快速参考：
? XRI 解析：类似通过UDP将主机名解析为IP的DNS协议；它将XRI转换为XRDS。其目的是提供一种将厚重、通用的XRI格式转换为真实可用的描述符。
? YADIS协议：将URL连接到XRDS上。这是一种非常简单的协议，它将当前的HTTP或者HTTPS URL直接指向XRDS。
? XRDS：一种基于XML的XRI资源描述符。它被设计用来提供关于XRI的可用的、描述性信息。在OpenID应用场合中，XRDS用来描述OpenID服务器，并且使用“priority”参数标识了用户对服务器的优选顺序。在下面的示例中，http://www.livejournal.com/users/frank具有最高的优先权（最低的数值）：
<?xml version="1.0" encoding="UTF-8"?><xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)"xmlns:openid="http://openid.net/xmlns/1.0"> <XRD> <Service priority="50"> <Type>http://openid.net/signon/1.0</Type> <URI>http://www.myopenid.com/server</URI> <openid:Delegate>http://smoker.myopenid.com/</openid:Delegate> </Service> <Service priority="10"> <Type>http://openid.net/signon/1.0</Type> <URI>http://www.livejournal.com/openid/server.bml</URI> <openid:Delegate>http://www.livejournal.com/users/frank/</openid:Delegate> </Service> <Service priority="20"> <Type>http://lid.netmesh.org/sso/2.0</Type> <URI>http://mylid.net/liddemouser</URI> </Service> </XRD></xrds:XRDS>
? 使用HTML代码。在HTML的<head>；部分必须提供以下标签：
<link rel="openid2.provider" href="http://openid.com/server/endpoint/url"/>
可选的，如果用户使用委派（delegation）（就是用户宣称拥有一个不存在于该OpenID服务器上的本地标识），则需要使用下面的标签：
<link rel="openid2.local_id" href="http://openid.com/server/endpoint/url"/>
例如，某人正在使用openidprovider.com这个OpenID服务器来验证他在另一个OpenID服务器usersite.com上的身份，那么其本地标识将使用类似user.openidprovider.com的形式。
这个“发现”的过程允许外部站点知道两件事，其中一件是外部站点如何与OpenID服务器进行通讯：
⒈OpenID提供者端点URL：OpenID提供者的最终URL（服务器URL）。
⒉认证协议版本： OpenID认证使用的协议版本。
作为可选的，如果用户使用委派，那么外部站点将需要知道：
⒈用户宣称的标识：此标识为用户宣称属于自己的。它是在登录过程中用户提供过的标识。
⒉本地标识（OP-Local Identifier）：用户在其OpenID服务器上拥有的本地标识。
4. Relying Party⒋ Relying Party站点建立与OpenID服务器之间的关联（可选）
通过在外部站点和OpenID服务器之间的关联（association），我们可以建立一种在两者之间共享的加密通道，它可以用来验证后续的协议信息并降低通讯回合数。在OpenID规范中对于实际创建关联的过程进行了详尽的描述。简单来讲就是使用了一种Diffie-Hellman密钥交换算法来生成共享密钥。此密钥用于对信息进行签名。
这样使得外部站点和OpenID服务器之间能够安全地通讯。这里指的“安全性”是通过传输层（使用SSL）或者通过应用层的HMAC SHA1或者HMAC SHA256算法实现的。关联请求的成果就是assoc_handle（关联权柄），外部站点和OpenID服务器将在本次关联的后继活动中将它作为对消息进行加密的密钥。
关联阶段被标为“可选的”，这是因为OpenID协议还允许外部站点直接请求认证（不作关联）、并且接着请求对认证信息进行验证。这样外部站点可以不保有关联权柄信息，以实现无状态通讯。而这种方式并不被推荐用于执行与OpenID服务器之间的相关通讯，只有当Relying Party无法保存关联句柄时候才采用。
5. Relying Party⒌ Relying Party站点请求认证
我们通过使用重定向页面可以建立认证请求。请查看下表中的重要参数值，详细信息请参考OpenID相关信息格式文档：
请注意：外部站点并没有直接发送HTTP请求到OpenID服务器，而是重定向到OpenID服务器页面。由于这样使得OpenID服务器能够从用户浏览器中读取cookie而没有将任何认证细节泄露给外部站点，因此这个过程是安全的。
6. OpenID⒍ OpenID服务器回应认证请求
在接收到OpenID认证请求后，OpenID服务器必须决定允许还是拒绝此用户的认证。这将由用户从前是否在OpenID服务器上认证过决定。
请注意：OpenID服务器在接收认证请求信息时是具有控制权的。这意味着它不但能够异步地回应认证请求信息，并在它回应认证请求之前与用户进行一系列的交互。大多数认证服务器都提供给用户一个页面使其能够选择允许或者拒绝来自外部站点的认证请求。
一旦OpenID服务器已经回应了认证请求，那么它将创建一个如下描述的认证回应信息，低层信息细节请阅读OpenID协议文档：
此回应通过将用户重定向到外部站点的方式发送，以确保外部站点和OpenID服务器之间在认证请求/回应过程中没有直接通讯。
7. 验证间接回应协议的最后一步是外部站点验证这个发自OpenID服务器的间接认证回应信息。
当外部站点接收到回应时，它必须在接受其内容之前进行下面的验证：
? “openid.return_to”的参数值是否匹配当前请求的URL。这确保OpenID服务器重定向用户、发送回应信息到正确的URL。
? 被发现的信息是否与回应信息相匹配。
? 具有相同参数值的“openid.response_nonce”表示OpenID服务器遭到了重放攻击(reply attacks）。
? 在回应信息中的签名是否有效、要求的签名域是否都被签名。这保证认证信息没有被篡改过。
协议扩展
OpenID协议提供了一个基本的认证机制。目前还有基于OpenID的其它可用协议：
? Attribute Exchange：OpenID属性交换是一种用于在端点之间交换标识信息OpenID服务扩展。其提供了对标识信息的接收和存储。
? Simple Registration：这是OpenID认证协议的扩展，它允许非常轻量级的配置交换。主要用于在终端用户使用web服务注册新帐号时传送八种常用的请求信息。
使用OpenID4Java实现OpenID协议
OpenID4Java是对OpenID1.1和2.0规范的实现，目前它通过code.google.com系统进行维护。此项目初始代码是由Sxip捐献出来的，而后Atlassian等公司参与进来，并为实现支持2.0规范（属性交换规范）的API贡献了大量的工作。
在使用OpenID4Java之前，你需要完成以下工作：
? 下载OpenID4Java代码库，并将其安装到你的项目中。
? 修改你的认证提示，使其询问用户的OpenID标识，而不是从前的用户名和密码。
? 创建针对用户标识的认证请求，并将用户重定向到他们的OpenID服务器。
? 在返回URL中接收OpenID提供者的认证回应并进行验证。
这样，你的web应用就会像在上面协议综述中的流程图所展示的“Relying Party”那样工作。
第一步是创建消费者对象，它将向认证服务器发出认证请求。这里我们将消费者对象视为一个贯穿应用的个体，以使相关的关联密钥能够保存在同一位置。因为当面临多个认证请求时，在不同的请求之间保存密钥将在两个端点（请求和回应端点）间引起下幅度的性能下降。
Sample Consumer代码片段：
/** * Sample Consumer (Relying Party) implementation. */public class SampleConsumer{ public ConsumerManager manager; public SampleConsumer() throws ConsumerException { // instantiate a ConsumerManager object manager = new ConsumerManager(); } ...}
一旦用户提供了OpenID URL，你就需要获取OpenID认证服务器的端点URL，发送请求到此URL。而OpenID认证服务器的端点被确定后，你还要创建一个和服务器关联的共享密钥。
// discover the OpenID authentication server's endpoint URLList discoveries = manager.discover(userSuppliedOpenID);// attempt to associate with the OpenID provider// and retrieve one service endpoint for authenticationDiscoveryInformation discovered = manager.associate(discoveries);// store the discovery information in the user's session for later usesession.setAttribute("discovered",discovered);
以上的调用将完成：
? 下载OpenID提供者列表（一般只有一个提供者）。返回结果将按照用户指定的优选顺序排列。
? 通过关联获取和OpenID提供者之间的共享密钥。
? 将关联（发现信息）保存，以备之后的使用。
我们现在需要将用户重定向到他们的OpenID提供者页面，并告诉OpenID提供者外部站点的地址（返回URL，这里就是你的站点），以使OpenID提供者知道在执行完认证后将用户发送到哪里。
// define the return pathString returnURL = "http://company.com/openidresponse.jsp";// generate an AuthRequest message to be sent to the OpenID providerAuthRequest authReq = manager.authenticate(discovered,returnURL);// redirect the user to their provider for authenticationhttpResp.sendRedirect(authReq.getDestinationUrl(true));
上面的代码将用户重定向到他们的OpenID提供者，在那里用户将被询问是否同意和你的站点进行认证。（请注意：无论用户同意“临时”授权给你的web应用、还是“总是”或者“不”授权，OpenID提供者都将保存此首选标识）。当用户再次访问你的web应用时，如果用户已经被OpenID提供者认证过并且在首次认证时选择了“总是”，那么此用户将可以访问你的web应用，而无需再次认证。
在认证用户之后，OpenID提供者将用户重定向到外部站点（由返回URL定义的web应用），并发送认证回应信息给你的web应用，而你的web应用将需要接收此回应。你可以显示错误信息或者将用户发送到“成功”页面，这完全取决于你的工作流。