作为此答案的原始作者,我想指出我认为它已经
过时了。由于大多数提供商决定专门实现Oauth而不是Openid。新的Openid服务也可能使用基于oauth的openid connect。有一些很好的库,例如:
https://github.com/hybridauth/hybridauth
在讨论了之前的回答后,我总结如下:
几乎每个主要提供商都是openid提供商/终端,包括Google、Yahoo和Aol。
其中一些要求用户指定用户名来构建openid终端点。其中一些(上面提到的那些)确实有发现URL,其中用户ID会自动返回,以便用户只需单击即可。(如果有人能解释一下技术背景,我会很高兴。)
然而,唯一麻烦的是Facebook,因为他们有他们的Facebook连接,其中他们使用OAuth的适应版本进行身份验证。
现在,我为我的项目设置了一个Openid提供程序,该提供程序使用我的Facebook应用程序的凭据对用户进行身份验证-因此用户与我的应用程序连接,并返回一个看起来像这样的用户ID:
http://my-facebook-openid-proxy-subdomain.mydomain.com/?id=facebook-user-id
我还配置了它来获取电子邮件地址和名称,并将其作为AX属性返回。
所以我的网站只需要实现OpenID,就可以正常工作 :)
我是使用这里的类构建的:http://gitorious.org/lightopenid
在我的index.php文件中,我只需像这样调用它:
<?php
require 'LightOpenIDProvider.php';
require 'FacebookProvider.php';
$op = new FacebookProvider;
$op->appid = 148906418456860;
$op->secret = 'mysecret';
$op->baseurl = 'http://fbopenid.2xfun.com';
$op->server();
?>
而FacebookProvider.php的源代码如下:
<?php
class FacebookProvider extends LightOpenIDProvider
{
public $appid = "";
public $appsecret = "";
public $baseurl = "";
public $select_id = true;
function __construct() {
$this->baseurl = rtrim($this->baseurl,'/');
parent::__construct();
if(isset($_GET['id'])) {
$this->select_id = false;
}
}
function setup($identity, $realm, $assoc_handle, $attributes)
{
$attributes = base64_encode(serialize($attributes));
$url = "https://graph.facebook.com/oauth/authorize?client_id=".$this->appid."&redirect_uri=";
$redirecturl = urlencode($this->baseurl.$_SERVER['REQUEST_URI'].'&attributes='.$attributes);
$url .= $redirecturl;
$url .= "&display=popup";
$url .= "&scope=email";
header("Location: $url");
exit();
}
function checkid($realm, &$attributes)
{
$code = isset($_GET["code"]) ? $_GET["code"] : false;
if(!$code) {
return false;
}
$url = "https://graph.facebook.com/oauth/access_token?client_id=148906418456860&redirect_uri=";
$redirecturl = ($this->baseurl.$_SERVER['REQUEST_URI']);
$redirecturl = strstr($redirecturl, '&code', true);
$redirecturl = urlencode($redirecturl);
$url .= $redirecturl;
$url .= "&client_secret=".$this->secret;
$url .= "&code=".$code;
$data = $this->get_data($url);
parse_str($data,$data);
$token = $data['access_token'];
$data = $this->get_data('https://graph.facebook.com/me?access_token='.urlencode($token));
$data = json_decode($data);
$id = $data->id;
$email = $data->email;
$attribute_map = array(
'namePerson/friendly' => 'name',
'contact/email' => 'email',
);
if($id > 0) {
$requested_attributes = unserialize(base64_decode($_GET["attributes"]));
$requested_attributes = array_merge($requested_attributes['required'],$requested_attributes['optional']);
$attributes = array();
foreach($requested_attributes as $requsted_attribute) {
if(!isset($data->{$attribute_map[$requsted_attribute]})) {
continue;
}
$attributes[$requsted_attribute] = $data->{$attribute_map[$requsted_attribute]};
}
return $this->serverLocation . '?id=' . $id ;
}
die('login failed');
return false;
}
function get_data($url) {
$ch = curl_init();
$timeout = 5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}
这只是第一个工作版本(快速而粗略)。
某些动态内容已经硬编码到我的需求中。
它应该展示如何以及可以做到。
如果有人拿起它并改进它或重新编写它,我会很高兴的:)
好吧,我认为这个问题已经得到了回答。
但我添加了赏金只是为了得到讨论。 我想知道您对我的解决方案的看法。
我将把奖励授予除此之外最佳的答案/评论。