最新的,支持 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.