最新的,支持 check_authentication 验证
演示地址:http://www.freebapp.org/tools/openid/
参考:
上一次的版本
OpenID登陆!
Yahoo的OpenID登陆
Windows Live ID当作OpenID使用的方法
Google的OpenID的登陆
<?php
error_reporting(0);
//ini_set('error_reporting', E_ALL);
//ini_set("display_errors", 1);
$LoginUrl = 'http://freebapp.org/tools/openid/';
$AuthUrl = 'http://freebapp.org/tools/openid/auth.php';
$RealmUrl = 'http://freebapp.org/';
$PolicyUrl = 'http://freebapp.org/policy_url.html';
if(!empty($_REQUEST['AuthType'])){
$AuthType = $_REQUEST['AuthType'];
setcookie('cookieAuthType', $AuthType);
}else{
if(!empty($_COOKIE['cookieAuthType'])){
$AuthType = $_COOKIE['cookieAuthType'];
}else{
LocationHtml($LoginUrl);
}
}
if(!empty($_REQUEST['return_to'])){
$ReturnToUrl = $_REQUEST['return_to'];
setcookie('cookieReturnTo', $ReturnToUrl);
}else{
if(!empty($_COOKIE['cookieReturnTo'])){
$ReturnToUrl = $_COOKIE['cookieReturnTo'];
}else{
$ReturnToUrl = $RealmUrl;
}
}
/*
if(!empty($_COOKIE['cookieAssocHandle'])){
$AssocHandle = $_COOKIE['cookieAssocHandle'];
}else{
$AssocHandle = null;
}
*/
switch($AuthType){
case 'Google':
if(empty($_REQUEST['openid_mode'])){
$openid_server = getXrdsUri('https://www.google.com/accounts/o8/id');
$data['openid.ns'] = 'http://specs.openid.net/auth/2.0';
$data['openid.mode'] = 'associate';
$data['openid.assoc_type'] = 'HMAC-SHA1';
$data['openid.session_type'] = 'DH-SHA1';
$AssocHandle = getAssociationHandle($openid_server.'?'.http_build_query($data));
//setcookie('cookieAssocHandle', $AssocHandle);
unset($data);
$data['openid.ns'] = 'http://specs.openid.net/auth/2.0';
$data['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select';
$data['openid.identity'] = 'http://specs.openid.net/auth/2.0/identifier_select';
$data['openid.return_to'] = $AuthUrl;
$data['openid.realm'] = $RealmUrl;
$data['openid.assoc_handle'] = $AssocHandle;
$data['openid.mode'] = 'checkid_setup';
$data['openid.ns.pape'] = 'http://specs.openid.net/extensions/pape/1.0';
$data['openid.ns.max_auth_age'] = 0;
$data['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
$data['openid.ax.mode'] = 'fetch_request';
$data['openid.ax.type.country'] = 'http://axschema.org/contact/country/home';
$data['openid.ax.type.email'] = 'http://axschema.org/contact/email';
$data['openid.ax.type.firstname'] = 'http://axschema.org/namePerson/first';
$data['openid.ax.type.language'] = 'http://axschema.org/pref/language';
$data['openid.ax.type.lastname'] = 'http://axschema.org/namePerson/last';
$data['openid.ax.required'] = 'country,email,firstname,language,lastname';
$LocationUrl = $openid_server.'?'.http_build_query($data);
}else{
if('id_res' == $_REQUEST['openid_mode']){
$openid_server = $_REQUEST['openid_op_endpoint'];
$openid_signed = getAuthenticationSigned($_REQUEST);
if(getAuthentication($openid_server, http_build_query($openid_signed))){
$openid = formUrl($_REQUEST['openid_claimed_id']);
$email = !empty($_REQUEST['openid_ax_value_email']) ? $_REQUEST['openid_ax_value_email'] : $_REQUEST['openid_ext1_value_email'];
$fullname = (!empty($_REQUEST['openid_ax_value_lastname']) ? $_REQUEST['openid_ax_value_lastname'] : $_REQUEST['openid_ext1_value_lastname']).' '.(!empty($_REQUEST['openid_ax_value_firstname']) ? $_REQUEST['openid_ax_value_firstname'] : $_REQUEST['openid_ext1_value_firstname']);
$nickname = !empty($_REQUEST['openid_ax_value_lastname']) ? $_REQUEST['openid_ax_value_lastname'] : $_REQUEST['openid_ext1_value_lastname'];
}else{
echo('<pre>');
echo("<a href=$LoginUrl>BACK</a>\n\n");
echo('Error!');
echo('</pre>');
exit;
}
}
}
break;
case 'Yahoo':
if(empty($_REQUEST['openid_mode'])){
$openid_server = 'https://open.login.yahooapis.com/openid/op/auth';
$data['openid.ns'] = 'http://specs.openid.net/auth/2.0';
$data['openid.mode'] = 'associate';
$data['openid.assoc_type'] = 'HMAC-SHA1';
$data['openid.session_type'] = 'DH-SHA1';
$AssocHandle = getAssociationHandle($openid_server.'?'.http_build_query($data));
//setcookie('cookieAssocHandle', $AssocHandle);
unset($data);
$data['openid.ns'] = 'http://specs.openid.net/auth/2.0';
$data['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select';
$data['openid.identity'] = 'http://specs.openid.net/auth/2.0/identifier_select';
$data['openid.return_to'] = $AuthUrl;
$data['openid.realm'] = $RealmUrl;
$data['openid.assoc_handle'] = $AssocHandle;
$data['openid.mode'] = 'checkid_setup';
$data['openid.ns.pape'] = 'http://specs.openid.net/extensions/pape/1.0';
$data['openid.ns.max_auth_age'] = 0;
$data['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
$data['openid.ax.mode'] = 'fetch_request';
$data['openid.ax.type.country'] = 'http://axschema.org/contact/country/home';
$data['openid.ax.type.email'] = 'http://axschema.org/contact/email';
$data['openid.ax.type.firstname'] = 'http://axschema.org/namePerson/first';
$data['openid.ax.type.language'] = 'http://axschema.org/pref/language';
$data['openid.ax.type.lastname'] = 'http://axschema.org/namePerson/last';
$data['openid.ax.required'] = 'country,email,firstname,language,lastname';
$data['xopenid.lang.pref'] = 'tw';
$LocationUrl = $openid_server.'?'.http_build_query($data);
}else{
if('id_res' == $_REQUEST['openid_mode']){
$openid_server = $_REQUEST['openid_op_endpoint'];
$openid_signed = getAuthenticationSigned($_REQUEST);
if(getAuthentication($openid_server, http_build_query($openid_signed))){
$openid = !empty($_REQUEST['openid_identity']) ? formUrl($_REQUEST['openid_identity']) : formUrl($_REQUEST['openid_claimed_id']);
$email = $_REQUEST['openid_ax_value_email'];
$fullname = (!empty($_REQUEST['openid_ax_value_lastname']) ? $_REQUEST['openid_ax_value_lastname'] : $_REQUEST['openid_ext1_value_lastname']).' '.(!empty($_REQUEST['openid_ax_value_firstname']) ? $_REQUEST['openid_ax_value_firstname'] : $_REQUEST['openid_ext1_value_firstname']);
$nickname = !empty($_REQUEST['openid_ax_value_lastname']) ? $_REQUEST['openid_ax_value_lastname'] : $_REQUEST['openid_ext1_value_lastname'];
$timezone = $_REQUEST['openid_ax_value_timezone'];
}else{
echo('<pre>');
echo("<a href=$LoginUrl>BACK</a>\n\n");
echo('Error!');
echo('</pre>');
exit;
}
}
}
break;
case 'Live':
$DEBUG = true;
$KEYFILE = './Live/Application-Key.xml';
$COOKIE = 'webauthtoken';
$COOKIETTL = time() + (10 * 365 * 24 * 60 * 60);
include_once('./Live/lib/windowslivelogin.php');
$wll = WindowsLiveLogin::initFromXml($KEYFILE);
$wll->setDebug($DEBUG);
if(!empty($_REQUEST['action'])){
switch($_REQUEST['action']) {
case 'logout':
setcookie($COOKIE);
$LocationUrl = $RealmUrl;
break;
case "clearcookie":
setcookie($COOKIE);
$LocationUrl = $AuthUrl;
break;
default:
$user = $wll->processConsent($_REQUEST);
if(!empty($user)){
setcookie($COOKIE, $user->getToken(), $COOKIETTL);
$LocationUrl = $AuthUrl;
}else{
$LocationUrl = $LoginUrl;
}
break;
}
LocationHtml($LocationUrl);
}
$token = $_COOKIE[$COOKIE];
if($token){
$user = $wll->processConsentToken($token);
if(!$user->isValid()){
$LocationUrl = $AuthUrl.'?AuthType=Live&action=clearcookie';
}else{
$url = 'https://livecontacts.services.live.com/users/@L@'.$user->getLocationID().'/rest/livecontacts/owner';
$owner = getLiveID($url, array('Authorization: DelegatedToken dt="'.$user->getDelegationToken().'"'));
$openid = $owner->WindowsLiveID.' | http://cid-'.$user->getLocationID().'.profile.live.com/';
$email = $owner->WindowsLiveID;
$fullname = $owner->Profiles->Personal->LastName.' '.$owner->Profiles->Personal->FirstName;
$nickname = $owner->Profiles->Personal->DisplayName;
echo('<pre>');
echo("<a href=$LoginUrl>BACK</a>\n\n");
print_r($owner);
echo('</pre>');
}
}else{
$LocationUrl = $wll->getConsentUrl('Contacts.View', 'zh-CN');
}
break;
case 'OpenID':
if(empty($_REQUEST['openid_mode'])){
if(empty($_REQUEST['OpenID']))
LocationHtml($LoginUrl, 'OpenID is null!');
$openid_url = formUrl($_REQUEST['OpenID']);
$openid_server_list = getOpenIDServer($openid_url);
if(empty($openid_server_list))
LocationHtml($LoginUrl, 'OpenID server is null!');
if(!empty($openid_server_list[1]))
$openid_server = $openid_server_list[1];
if(!empty($openid_server_list[2]))
$openid_server = $openid_server_list[2];
if(!empty($openid_server_list[3]))
$openid_url = $openid_server_list[3];
$data['openid.ns'] = 'http://specs.openid.net/auth/2.0';
$data['openid.mode'] = 'associate';
$data['openid.assoc_type'] = 'HMAC-SHA1';
$data['openid.session_type'] = 'DH-SHA1';
$AssocHandle = getAssociationHandle($openid_server.'?'.http_build_query($data));
setcookie('cookieAssocHandle', $AssocHandle);
unset($data);
$data['openid.assoc_handle'] = $AssocHandle;
$data['openid.claimed_id'] = $openid_url;
$data['openid.identity'] = $openid_url;
$data['openid.mode'] = 'checkid_setup';
$data['openid.ns'] = 'http://specs.openid.net/auth/2.0';
$data['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
$data['openid.realm'] = $RealmUrl;
$data['openid.return_to'] = $AuthUrl;
$data['openid.sreg.optional'] = 'nickname,email,fullname,dob,gender,postcode,country,language,timezone';
$data['openid.sreg.policy_url'] = $PolicyUrl;
$data['openid.sreg.required'] = 'email';
$data['openid.trust_root'] = $RealmUrl;
$LocationUrl = $openid_server.'?'.http_build_query($data);
}else{
if('id_res' == $_REQUEST['openid_mode']){
$openid_server = $_REQUEST['openid_op_endpoint'];
$openid_signed = getAuthenticationSigned($_REQUEST);
if(getAuthentication($openid_server, http_build_query($openid_signed))){
$openid = !empty($_REQUEST['openid_claimed_id']) ? formUrl($_REQUEST['openid_claimed_id']) : formUrl($_REQUEST['openid_identity']);
$email = $_REQUEST['openid_sreg_email'];
$fullname = $_REQUEST['openid_sreg_fullname'];
$nickname = $_REQUEST['openid_sreg_nickname'];
$timezone = $_REQUEST['openid_sreg_timezone'];
}else{
echo('<pre>');
echo("<a href=$LoginUrl>BACK</a>\n\n");
echo('Error!');
echo('</pre>');
exit;
}
}
}
break;
default:
LocationHtml($LoginUrl);
}
if(empty($openid))
LocationHtml($LocationUrl);
echo('<pre>');
echo("<a href=$LoginUrl>BACK</a>\n\n");
print_r($_REQUEST);
echo('</pre>');
echo('<pre>');
echo("openid : $openid\n");
echo("email : $email\n");
echo("fullname: $fullname\n");
echo("nickname: $nickname\n");
echo("timezone: $timezone\n");
echo('</pre>');
function getLiveID($url, $header){
$d = getCurl($url, '', $header);
if(200 != $d['header']['http_code']){
return false;
}
try{
$xml = new SimpleXMLElement($d['data']);
}catch(Exception $e){
return false;
}
return $xml;
}
function getOpenIDServer($url){
$d = getCurl($url);
if(200 != $d['header']['http_code']){
return false;
}
$s = array();
preg_match("/\<link rel=\"openid\.server\" href=\"([^\"]+)\"( )?(\/)?\>/i", $d['data'], $matches);
if(!empty($matches))
$s[1] = $matches[1];
preg_match("/\<link rel=\"openid2\.provider\" href=\"([^\"]+)\"( )?(\/)?\>/i", $d['data'], $matches);
if(!empty($matches))
$s[2] = $matches[1];
preg_match("/\<link rel=\"openid\.delegate\" href=\"([^\"]+)\"( )?(\/)?\>/i", $d['data'], $matches);
if(!empty($matches))
$s[3] = $matches[1];
return $s;
}
function formUrl($url){
$urls = parse_url($url);
$scheme = 'http';
if(empty($urls['scheme']))
$urls = parse_url($scheme.'://'.$url);
else
$scheme = $urls['scheme'];
if(empty($urls['host']))
$host = '';
else
$host = $urls['host'];
if(empty($urls['path']))
$path = '/';
else
$path = $urls['path'];
if('/' != $path){
$path = ereg_replace('/$', '', $path);
}
if(empty($urls['query']))
$query = '';
else
$query = '?'.$urls['query'];
return strtolower($scheme.'://'.$host).$path.$query;
}
function getXrdsUri($url){
$d = getCurl($url);
if(200 != $d['header']['http_code']){
return '';
}
$domdoc = new DOMDocument();
$domdoc->loadXML($d['data']);
$uri = $domdoc->getElementsByTagName("URI");
$uri = $uri->item(0)->nodeValue;
return $uri;
}
function getAssociationHandle($url){
$d = getCurl($url);
if(200 != $d['header']['http_code']){
return '';
}
$assoc_handle = '';
$lines = explode("\n", $d['data']);
foreach($lines as $line){
if(substr($line, 0, 13) == "assoc_handle:"){
$assoc_handle = substr($line, 13);
break;
}
}
return $assoc_handle;
}
function getAuthentication($url, $data=null){
$d = getCurl($url, $data);
if(200 == $d['header']['http_code']){
if(false !== strpos($d['data'], 'is_valid:true')){
return true;
}else{
return false;
}
}else{
return false;
}
}
function getCurl($url, $data=null, $header=null){
$c = curl_init($url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
if(!empty($data)){
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, $data);
}
if(!empty($header)){
curl_setopt($c, CURLOPT_HTTPHEADER, $header);
}
$d['data'] = curl_exec($c);
$d['header'] = curl_getinfo($c);
curl_close($c);
return $d;
}
function getAuthenticationSigned($d){
$data["openid.assoc_handle"] = $d['openid_assoc_handle'];
$data["openid.sig"] = $d['openid_sig'];
$data["openid.signed"] = $d['openid_signed'];
//$arr_underscores = array('ns_', 'pape_', 'sreg_');
//$arr_periods = array('ns.', 'pape.', 'sreg.');
//$arr_signed = explode(",", str_replace($arr_periods, $arr_underscores, $_REQUEST["openid_signed"]));
$arr_signed = explode(',', $d['openid_signed']);
for($i=0; $i<count($arr_signed); $i++){
$s = str_replace('.', '_', $arr_signed[$i]);
$c = $d['openid_'.$s];
//if($c != ""){
$data['openid.'.$arr_signed[$i]] = $c;
//}
}
$data['openid.mode'] = 'check_authentication';
return $data;
}
function LocationHtml($url, $e=null){
if(empty($url))
exit;
echo('<html>');
echo('<head>');
echo('<title>Redirect to: '.$url.'</title>');
echo('<meta http-equiv="refresh" content="1;url='.$url.'">');
echo('</head>');
echo('<body bgcolor="#FFFFFF" onload="window.location.href=\''.$url.'\'">');
echo('<table border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" height="100%" width="100%">');
echo('<tr>');
echo('<td align="center" valign="middle">');
echo('<a href="'.$url.'" style="color:#000000;text-decoration:none">');
echo('<img src="http://freebapp.org/static/images/location.gif" border="0" alt="Redirect to: '.$url.'" title="Redirect to: '.$url.'"/>');
echo('</a>');
echo('</td>');
echo('</tr>');
echo('</table>');
if(!empty($e)){
echo('<script type="text/javascript">');
if(is_array($e))
echo('alert("'.implode('\n', $e).'");');
else
echo('alert("'.$e.'");');
echo('</script>');
}
echo('</body>');
echo('</html>');
exit;
}
?>
10 Comments
如果有注释就好了,我研读了一下才看明白,挺好用:)
拿不到yahoo的数据
这个代码有人维护不?
王炜大哥,通过你提供的方法以上的功能我都实现了,但是现在我有一个问题,就是登陆后怎样判断用户还未退出,比如用google用户来说,用户通过验证登陆到了我的应用程序中(也登陆到了google),但是此时用户退出google登陆,刷新我应用程序,我怎样判断此用户已经退出google要求他从新登陆
这似乎无法判断,openid只是提供用户身份的识别,而不理会openid提供商的状态。这样对“记住用户身份”的网站有安全的漏洞!
您写过facebook接口吗,请问facebook中可以实现获取用户的邮箱吗?
你好王炜
我出现这个错误
不知道如何解决了
https://consent.live.com/pp900/Error.aspx?mkt=zh-CN&ErrorCode=2002
貌似您的google/yahoo的associate过程没有成功。$data[‘openid.session_type’] = ‘DH-SHA1’;要设置dh_module dh_gen dh_consumer_public 才可以。
王炜:
您好!我是一名在校学生,对openid比较感兴趣。在进行实践过程中,遇到如下的问题,想请教一下您!
1:在openid2.0协议里边描述:
1.1:收到一个针对”checkid_immediated”模式请求的否定断言的时候,RP应该使用“check_setup”模式构造一个新的认证请求。
1.2:针对及时请求的否定断言满足以下形式:
openid.ns:略
openid.mode:setup_needed
我现在的疑惑:
1:在什么情况下会遇到即时请求的否定断言?
2:您方便的话,可以给我举一个关于终端用户在登录过程中遇到“即时请求的否定断言”这种情况的实例吗?
谢谢您!
我的邮箱:yanghaoquan@126.com
People deserve very good life and home loans or financial loan can make it better. Just because people’s freedom depends on money.