phpbb 第三方登录该怎么做呢?

2011-04-09 12:01:19 +08:00
 dbfox
phpbb 第三方登录该怎么做呢?
我想使用 Google OpenID 作为登录账户
省去 我的论坛的注册
<?php

/****************************************************************************
* The GoogleOpenID class
*
* This class implements a gateway to the Google OpenID federated login API
*
* By Andrew Peace (http://www.andrewpeace.com)
* December 6, 2008
* Contact me at http://www.andrewpeace.com/contact.html
*
*
* Usage:
*
* To redirect users to a Google login page, simply create a GoogleOpenID:
*
* $googleGateway = GoogleOpenID::createRequest("http://www.mydomain.com/check.php",
* "ABCDEFG",
* true);
*
* The first argument is the URL you want Google to redirect to when it sends
* its response
*
* The second argument is the association handle you've obtained from Google.
* This parameter is OPTIONAL and can be set to null. However, if it is not
* given or it is set to null, GoogleOpenID will automatically request an
* association handle when it is constructed. This is wastefull! Association
* handles last for two weeks. So, it is better to get and save an association
* handle on your own using GoogleOpenID::getAssociationHandle().
*
* The third argument should be set to true if you want the response to include
* the user's email address. It is optional.
*
* Example:
*
* $googleGateway = GoogleOpenID::createRequest("http://www.mydomain.com/checkauth.php", "ABCDEFG", true);
* $googleGateway->redirect();
*
* OR
*
* $handle = GoogleOpenID::getAssociationHandle(); // <--save this! valid for two weeks!
*
* $googleGateway = GoogleOpenID::createRequest("http://www.mydomain.com/checkauth.php", $handle, true);
* $googleGateway->redirect();
*
*
* When you want to recieve a Google OpenID response, simply pass the given
* parameters to GoogleOpenID::create(). In most cases, you should just be able
* to pass the $_GET variable.
*
* To continue the previous example, the following code would go in checkauth.php
*
* $googleResponse = GoogleOpenID::create($_GET);
* $sucess = $googleResponse->success();//true or false
* $user_identity = $googleResponse->identity();//the user's ID
* $user_email = $googleResponse->email();//the user's email
*
* OR, even easier
*
* $googleResponse = GoogleOpenID::getResponse(); // <-- automatically reads $_GET
*
* Advanced users can create a slightly more customized request using the create
* method. It accepts an associative array of openid parameters and sets those
* that it deems appropriate to set (mostly, the parameters that don't have a
* definite value when interacting with Google)
*
*
* Full class signature:
*
* public static createRequest(String, [String], [Boolean])
* public static getResponse()
* public static create(Array)
* public static getAssociationHandle([String])
* public static getEndPoint()
* public redirect()
* public getArray()
* public endPoint()
* public success()
* public assoc_handle()
* public email()
* public identity()
*
* Features to implement:
*
* -In constructor, fix relative->absolute URL conversion (it is messy/buggy)
* -In getAssociationHandle(), use encryption
* -Verify Google's response with signed, sig etc
****************************************************************************/

class GoogleOpenID{
//the google discover url
const google_discover_url = "https://www.google.com/accounts/o8/id";

//some constant parameters
const openid_ns = "http://specs.openid.net/auth/2.0";
//required for email attribute exchange
const openid_ns_ext1 = "http://openid.net/srv/ax/1.0";
const openid_ext1_mode = "fetch_request";
const openid_ext1_type_email = "http://schema.openid.net/contact/email";
const openid_ext1_required = "email";

//parameters set by constructor
private $mode;//the mode (checkid_setup, id_res, or cancel)
private $response_nonce;
private $return_to;//return URL
private $realm;//the realm that the user is being asked to trust
private $assoc_handle;//the association handle between this service and Google
private $claimed_id;//the id claimed by the user
private $identity;//for google, this is the same as claimed_id
private $signed;
private $sig;
private $email;//the user's email address

//if true, fetch email address
private $require_email;

//private constructor
private function GoogleOpenID($mode, $op_endpoint, $response_nonce, $return_to, $realm, $assoc_handle, $claimed_id, $signed, $sig, $email, $require_email){

//if assoc_handle is null, fetch one
if(is_null($assoc_handle))
$assoc_handle = GoogleOpenID::getAssociationHandle();

//if return_to is a relative URL, make it absolute
if(stripos($return_to, "http://")==false &&
stripos($return_to, "https://")==false){
//if the first character is a slash, delete it
if(substr($return_to, 0, 1)=="/")
$return_to = substr($return_to, 1);
//get the position of server_name
$server_name_pos = stripos($return_to, $_SERVER['SERVER_NAME']);
//if server_name is already at position zero
if($server_name_pos != false && $server_name_pos==0){
$return_to = "http://".$return_to;
} else {
$return_to = "http://".$_SERVER['SERVER_NAME']."/".$return_to;
}//else (server name not at position zero)
}//if return_to is relative

//if realm is null, attempt to set it via return_to
if(is_null($realm)){
//if return_to is set
if(!is_null($return_to)){
$pieces = parse_url($return_to);
$realm = $pieces['scheme']."://".$pieces['host'];
}//if return_to set
}//if realm null

$this->mode = $mode;
$this->op_endpoint = $op_endpoint;
$this->response_nonce = $response_nonce;
$this->return_to = $return_to;
$this->realm = $realm;
$this->assoc_handle = $assoc_handle;
$this->claimed_id = $claimed_id;
$this->identity = $claimed_id;
$this->signed = $signed;
$this->sig = $sig;
$this->email = $email;
$this->require_email = ($require_email) ? true : false;
}//GoogleOpenID

//static creator that accepts only a return_to URL
//this creator should be used when creating a GoogleOpenID for a redirect
public static function createRequest($return_to, $assoc_handle=null, $require_email=false){
return new GoogleOpenID("checkid_setup", null, null, $return_to, null, $assoc_handle, "http://specs.openid.net/auth/2.0/identifier_select", null, null, null, $require_email);
}//createRequest

//static creator that accepts an associative array of parameters and
//sets only the setable attributes (does not overwrite constants)
public static function create($params){
//loop through each parameter
foreach($params as $param => $value){
switch($param){
case "openid_mode":
//check validity of mode
if($value=="checkid_setup" ||
$value=="id_res" ||
$value=="cancel")
$mode = $value;
else
$mode = "cancel";
continue 2;

case "openid_op_endpoint":
$op_endpoint = $value;
continue 2;

case "openid_response_nonce":
$response_nonce = $value;
continue 2;

case "openid_return_to":
$return_to = $value;
continue 2;

case "openid_realm":
$realm = $value;
continue 2;

case "openid_assoc_handle":
$assoc_handle = $value;
continue 2;

case "openid_claimed_id":
$claimed_id = $value;
continue 2;

case "openid_identity":
$claimed_id = $value;
continue 2;

case "openid_signed":
$signed = $value;
continue 2;

case "openid_sig":
$sig = $value;
continue 2;

case "openid_ext1_value_email":
$email = $value;
continue 2;

case "require_email":
$require_email = $value;
continue 2;

default:
continue 2;
}//switch param
}//loop through params

//if require email is not set, set it to false
if(!is_bool($require_email))
$require_email = false;
//if mode is not set, set to default for redirection
if(is_null($mode))
$mode = "checkid_setup";
//if return_to is not set and mode is checkid_setup, throw an error
if(is_null($return_to) && $mode=="checkid_setup")
throw new Exception("GoogleOpenID.create() needs parameter openid.return_to");

//return a new GoogleOpenID with the given parameters
return new GoogleOpenID($mode, $op_endpoint, $response_nonce, $return_to, $realm, $assoc_handle, $claimed_id, $signed, $sig, $email, $require_email);
}//create

//creates and returns a GoogleOpenID from the $_GET variable
public static function getResponse(){
return GoogleOpenID::create($_GET);
}//getResponse

//fetches an association handle from google. association handles are valid
//for two weeks, so coders should do their best to save association handles
//externally and pass them to createRequest()
//NOTE: This function does not use encryption, but it SHOULD! At the time
//I wrote this I wanted it done fast, and I couldn't seem to find a good
//two-way SHA-1 or SHA-256 library for PHP. Encryption is not my thing, so
//it remains unimplemented.
public static function getAssociationHandle($endpoint=null){
//if no endpoint given
if(is_null($endpoint))
//fetch one from Google
$request_url = GoogleOpenID::getEndPoint();
//if endpoint given, set it
else
$request_url = $endpoint;

//append parameters (these never change)
$request_url .= "?openid.ns=".urlencode(GoogleOpenID::openid_ns);
$request_url .= "&openid.mode=associate";
$request_url .= "&openid.assoc_type=HMAC-SHA1";
$request_url .= "&openid.session_type=no-encryption";

//create a CURL session with the request URL
$c = curl_init($request_url);

//set a few options
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_HEADER, false);

//get the contents of request URL
$request_contents = curl_exec($c);

//close the CURL session
curl_close($c);

//a handle to be returned
$assoc_handle = null;

//split the response into lines
$lines = explode("\n", $request_contents);

//loop through each line
foreach($lines as $line){
//if this line is assoc_handle
if(substr($line, 0, 13)=="assoc_handle:"){
//save the assoc handle
$assoc_handle = substr($line, 13);
//exit the loop
break;
}//if this line is assoc_handle
}//loop through lines

//return the handle
return $assoc_handle;
}//getAssociationHandle

//fetches an endpoint from Google
public static function getEndPoint(){
//fetch the request URL
$request_url = GoogleOpenID::google_discover_url;

//create a CURL session with the request URL
$c = curl_init($request_url);

//set a few options
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_HEADER, false);

//fetch the contents of the request URL
$request_contents = curl_exec($c);

//close the CURL session
curl_close($c);

//create a DOM document so we can extract the URI element
$domdoc = new DOMDocument();
$domdoc->loadXML($request_contents);

//fetch the contents of the URI element
$uri = $domdoc->getElementsByTagName("URI");
$uri = $uri->item(0)->nodeValue;

//return the given URI
return $uri;
}//getEndPoint

//returns an associative array of all openid parameters for this openid
//session. the array contains all the GET attributes that would be sent
//or that have been recieved, meaning:
//
//if mode = "cancel" returns only the mode and ns attributes
//if mode = "id_res" returns all attributes that are not null
//if mode = "checkid_setup" returns only attributes that need to be sent
// in the HTTP request
public function getArray(){
//an associative array to return
$ret = array();

$ret['openid.ns'] = GoogleOpenID::openid_ns;

//if mode is cancel, return only ns and mode
if($this->mode=="cancel"){
$ret['openid.mode'] = "cancel";
return $ret;
}//if cancel

//set attributes that are returned for all cases
if(!is_null($this->claimed_id)){
$ret['openid.claimed_id'] = $this->claimed_id;
$ret['openid.identity'] = $this->claimed_id;
}
if(!is_null($this->return_to))
$ret['openid.return_to'] = $this->return_to;
if(!is_null($this->realm))
$ret['openid.realm'] = $this->realm;
if(!is_null($this->assoc_handle))
$ret['openid.assoc_handle'] = $this->assoc_handle;
if(!is_null($this->mode))
$ret['openid.mode'] = $this->mode;

//set attributes that are returned only if this is a request
//and if getting email is required OR if this is a response and the
//email is given
if(($this->mode=="checkid_setup" AND $this->require_email) OR
($this->mode=="id_res" AND !is_null($this->email))){
$ret['openid.ns.ext1'] = GoogleOpenID::openid_ns_ext1;
$ret['openid.ext1.mode'] = GoogleOpenID::openid_ext1_mode;
$ret['openid.ext1.type.email'] = GoogleOpenID::openid_ext1_type_email;
$ret['openid.ext1.required'] = GoogleOpenID::openid_ext1_required;
if(!is_null($this->email))
$ret['openid.ext1.value.email'] = $this->email;
}//if redirect and get email

//set attributes that are returned only if this is a response
if($this->mode=="id_res"){
$ret['openid.op_endpoint'] = $this->op_endpoint;
if(!is_null($this->response_nonce))
$ret['openid.response_nonce'] = $this->response_nonce;
if(!is_null($this->signed))
$ret['openid.signed'] = $this->signed;
if(!is_null($this->sig))
$ret['openid.sig'] = $this->sig;
}

//return the array
return $ret;
}//getArray

//sends a request to google and fetches the url to which google is asking
//us to redirect (unless the endpoint is already known, in which case the
//function simply returns it)
public function endPoint(){
//if we know the value of op_endpoint already
if(!is_null($this->op_endpoint))
return $this->op_endpoint;

//fetch the endpoint from Google
$endpoint = GoogleOpenID::getEndPoint();

//save it
$this->op_endpoint = $endpoint;

//return the endpoint
return $endpoint;
}//getedPoint

//returns the URL to which we should send a request (including all GET params)
private function getRequestURL(){
//get all parameters
$params = $this->getArray();

//the base URL
$url = $this->endPoint();

//flag indicating whether to set a '?' or an '&'
$first_attribute = true;

//loop through all params
foreach($params as $param => $value){
//if first attribute print a ?, else print a &
if($first_attribute){
$url .= "?";
$first_attribute = false;
} else {
$url .= "&";
}//else (not first attribute)

$url .= urlencode($param) . "=" . urlencode($value);
}//loop through params

//return the URL
return $url;
}//getRequestURL

//redirects the browser to the appropriate request URL
public function redirect(){
header("Location: ".$this->getRequestURL());
}//redirect

//returns true if the response was a success
public function success(){
return ($this->mode=="id_res");
}//success

//returns the identity given in the response
public function identity(){
if($this->mode!="id_res")
return null;
else
return $this->claimed_id;
}//identity

//returns the email given in the response
public function email(){
if($this->mode!="id_res")
return null;
else
return $this->email;
}//email

//returns the assoc_handle
public function assoc_handle(){
return $this->assoc_handle();
}//assoc_handle
}//class GoogleOpenID
?>
6211 次点击
所在节点    程序员
1 条回复
TheOnly92
2011-04-09 12:23:29 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/11201

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX