Janrain的OpenID PHP库登录后无法检索Google用户信息

Janrain的OpenID PHP库登录后无法检索Google用户信息,php,openid,google-openid,janrain,openid-provider,Php,Openid,Google Openid,Janrain,Openid Provider,我开始说我讨厌OpenID,因为它的实现/文档记录很差 我正在尝试使用openid-php-openid-2.2.2-24。下面是源代码: 当我尝试使用身份验证示例时,它返回给我: 您已成功验证https://www.google.com/accounts/o8/id?id=[…]作为你的身份 提供商未发送PAPE响应 但谷歌openid登录数据中没有电子邮件、昵称或全名的影子。 在阅读文件/openid/examples/consumer/finish_auth.php时,我注意到必须在您已成

我开始说我讨厌OpenID,因为它的实现/文档记录很差

我正在尝试使用openid-php-openid-2.2.2-24。下面是源代码:

当我尝试使用身份验证示例时,它返回给我: 您已成功验证https://www.google.com/accounts/o8/id?id=[…]作为你的身份

提供商未发送PAPE响应

但谷歌openid登录数据中没有电子邮件、昵称或全名的影子。 在阅读文件/openid/examples/consumer/finish_auth.php时,我注意到必须在您已成功验证和无PAPE响应消息之间打印SREG变量,但它们没有:

    $success = sprintf('You have successfully verified ' .
                       '<a href="%s">%s</a> as your identity.',
                       $esc_identity, $esc_identity);

    if ($response->endpoint->canonicalID) {
        $escaped_canonicalID = escape($response->endpoint->canonicalID);
        $success .= '  (XRI CanonicalID: '.$escaped_canonicalID.') ';
    }

    $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);

    $sreg = $sreg_resp->contents();

    if (@$sreg['email']) {
        $success .= "  You also returned '".escape($sreg['email']).
            "' as your email.";
    }

    if (@$sreg['nickname']) {
        $success .= "  Your nickname is '".escape($sreg['nickname']).
            "'.";
        $_SESSION['nickname'] = escape($sreg['nickname']);
    }

    if (@$sreg['fullname']) {
        $success .= "  Your fullname is '".escape($sreg['fullname']).
            "'.";
    }

$pape_resp = Auth_OpenID_PAPE_Response::fromSuccessResponse($response);

if ($pape_resp) {
    [...]
} else {
        $success .= "<p>No PAPE response was sent by the provider.</p>";
}
我试图打印$sreg['email']、$sreg['昵称']和$sreg['fullname']的内容,但它们返回所有空白内容null/空值

我需要检索用户用于登录的帐户的电子邮件地址


但丁

为了把这个问题从未回答的问题列表中去掉,我把但丁的回答作为答案贴在这里:

我解决了我的问题。 PHP OpenID中AX的使用示例: 经过两天的研究,我刚刚找到了答案,但谷歌使用AX属性交换而不是SReg来获取更多数据。为什么谷歌总是如此与众不同

但是,stackoverflow应答页中的代码对我不起作用。我的托管服务器返回500个内部服务器错误代码。 所以,我在这里发布了我的代码,它太粗糙了:

oid_ax_common.php

<?php

// Circumnavigate bugs in the GMP math library that can be result in signature
// validation errors
define('Auth_OpenID_BUGGY_GMP', true);

$path_extra = dirname(dirname(dirname(__FILE__)));
$path = ini_get('include_path');
$path = $path_extra . PATH_SEPARATOR . $path;
ini_set('include_path', $path);


function displayError($message) {
    $error = $message;
    include './index.php';
    exit(0);
}

function doIncludes() {
    /**
     * Require the OpenID consumer code.
     */
    require_once "Auth/OpenID/Consumer.php";

    /**
     * Require the "file store" module, which we'll need to store
     * OpenID information.
     */
    require_once "Auth/OpenID/FileStore.php";

    /**
     * Require the Simple Registration extension API.
     */
    //require_once "Auth/OpenID/SReg.php";
    require_once "Auth/OpenID/AX.php";

    /**
     * Require the PAPE extension module.
     */
    require_once "Auth/OpenID/PAPE.php";
}

doIncludes();

global $pape_policy_uris;
$pape_policy_uris = array(
              PAPE_AUTH_MULTI_FACTOR_PHYSICAL,
              PAPE_AUTH_MULTI_FACTOR,
              PAPE_AUTH_PHISHING_RESISTANT
              );

function &getStore() {
    /**
     * This is where the example will store its OpenID information.
     * You should change this path if you want the example store to be
     * created elsewhere.  After you're done playing with the example
     * script, you'll have to remove this directory manually.
     */
    $store_path = null;
    if (function_exists('sys_get_temp_dir')) {
        $store_path = sys_get_temp_dir();
    }
    else {
        if (strpos(PHP_OS, 'WIN') === 0) {
            $store_path = $_ENV['TMP'];
            if (!isset($store_path)) {
                $dir = 'C:\Windows\Temp';
            }
        }
        else {
            $store_path = @$_ENV['TMPDIR'];
            if (!isset($store_path)) {
                $store_path = '/tmp';
            }
        }
    }
    $store_path = './tmp/';
    $store_path .= DIRECTORY_SEPARATOR . '_php_consumer_test';

    if (!file_exists($store_path) &&
        !mkdir($store_path)) {
        print "Could not create the FileStore directory '$store_path'. ".
            " Please check the effective permissions.";
        exit(0);
    }
    $r = new Auth_OpenID_FileStore($store_path);

    return $r;
}

function &getConsumer() {
    /**
     * Create a consumer object using the store object created
     * earlier.
     */
    $store = getStore();
    $r = new Auth_OpenID_Consumer($store);
    return $r;
}

function getScheme() {
    $scheme = 'http';
    if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') {
        $scheme .= 's';
    }
    return $scheme;
}

function getReturnTo() {
    return sprintf("%s://%s:%s%s/oid_ax_receive.php",
                   getScheme(), $_SERVER['SERVER_NAME'],
                   $_SERVER['SERVER_PORT'],
                   dirname($_SERVER['PHP_SELF']));
}

function getTrustRoot() {
    return sprintf("%s://%s:%s%s/",
                   getScheme(), $_SERVER['SERVER_NAME'],
                   $_SERVER['SERVER_PORT'],
                   dirname($_SERVER['PHP_SELF']));
}

?>
oid_ax_send.php

<?php

require_once "oid_ax_common.php";
// Starts session (needed for YADIS)
session_start();

function getOpenIDURL() {
    // Render a default page if we got a submission without an openid
    // value.
    if (empty($_GET['openid_identifier'])) {
        $error = "Expected an OpenID URL.";
        include './index.php';
        exit(0);
    }

    return $_GET['openid_identifier'];
}

function run() {
    // https://www.google.com/accounts/o8/id
    // $openid = 'http://openid-provider.appspot.com/';
    $openid = 'https://www.google.com/accounts/o8/id';
    // $openid .= getOpenIDURL();
    $consumer = getConsumer();

    // Begin the OpenID authentication process.
    $auth_request = $consumer->begin($openid);

    // Create attribute request object
    // See http://code.google.com/apis/accounts/docs/OpenID.html#Parameters for parameters
    // Usage: make($type_uri, $count=1, $required=false, $alias=null)
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/contact/email',2,1, 'email');
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/first',1,1, 'firstname');
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/last',1,1, 'lastname');

    // Create AX fetch request
    $ax = new Auth_OpenID_AX_FetchRequest;

    // Add attributes to AX fetch request
    foreach($attribute as $attr){
        $ax->add($attr);
    }

    // Add AX fetch request to authentication request
    $auth_request->addExtension($ax);

    // No auth request means we can't begin OpenID.
    if (!$auth_request) {
        displayError("Authentication error; not a valid OpenID.");
    }

    /* $sreg_request = Auth_OpenID_SRegRequest::build(
                                     // Required
                                     array('nickname'),
                                     // Optional
                                     array('fullname', 'email'));

    if ($sreg_request) {
        $auth_request->addExtension($sreg_request);
    } */

    $policy_uris = null;
    if (isset($_GET['policies'])) {
        $policy_uris = $_GET['policies'];
    }

    $pape_request = new Auth_OpenID_PAPE_Request($policy_uris);
    if ($pape_request) {
        $auth_request->addExtension($pape_request);
    }

    // Redirect the user to the OpenID server for authentication.
    // Store the token for this authentication so we can verify the
    // response.

    // For OpenID 1, send a redirect.  For OpenID 2, use a Javascript
    // form to send a POST request to the server.
    if ($auth_request->shouldSendRedirect()) {
        $redirect_url = $auth_request->redirectURL(getTrustRoot(),
                                                   getReturnTo());

        // If the redirect URL can't be built, display an error
        // message.
        if (Auth_OpenID::isFailure($redirect_url)) {
            displayError("Could not redirect to server: " . $redirect_url->message);
        } else {
            // Send redirect.
            header("Location: ".$redirect_url);
        }
    } else {
        // Generate form markup and render it.
        $form_id = 'openid_message';
        $form_html = $auth_request->htmlMarkup(getTrustRoot(), getReturnTo(),
                                               false, array('id' => $form_id));

        // Display an error if the form markup couldn't be generated;
        // otherwise, render the HTML.
        if (Auth_OpenID::isFailure($form_html)) {
            displayError("Could not redirect to server: " . $form_html->message);
        } else {
            print $form_html;
        }
    }
}

run();

?>
oid_ax_receive.php

<?php

require_once "oid_ax_common.php";
// Starts session (needed for YADIS)
session_start();

function escape($thing) {
    return htmlentities($thing);
}

function run() {
    $consumer = getConsumer();

    // Complete the authentication process using the server's
    // response.
    $return_to = getReturnTo();
    $response = $consumer->complete($return_to);

    // Check the response status.
    if ($response->status == Auth_OpenID_CANCEL) {
        // This means the authentication was cancelled.
        $msg = 'Verification cancelled.';
    } else if ($response->status == Auth_OpenID_FAILURE) {
        // Authentication failed; display the error message.
        $msg = "OpenID authentication failed: " . $response->message;
    } else if ($response->status == Auth_OpenID_SUCCESS) {
        // Get registration informations
        $ax = new Auth_OpenID_AX_FetchResponse();
        $obj = $ax->fromSuccessResponse($response);

        // Print me raw
        echo '<pre>';
        print_r($obj->data);
        echo '</pre>';
        exit;

        $pape_resp = Auth_OpenID_PAPE_Response::fromSuccessResponse($response);

        if ($pape_resp) {
            if ($pape_resp->auth_policies) {
                $success .= "<p>The following PAPE policies affected the authentication:</p><ul>";

                foreach ($pape_resp->auth_policies as $uri) {
                    $escaped_uri = escape($uri);
                    $success .= "<li><tt>$escaped_uri</tt></li>";
                }

                $success .= "</ul>";
            } else {
                $success .= "<p>No PAPE policies affected the authentication.</p>";
            }

            if ($pape_resp->auth_age) {
                $age = escape($pape_resp->auth_age);
                $success .= "<p>The authentication age returned by the " .
                    "server is: <tt>".$age."</tt></p>";
            }

            if ($pape_resp->nist_auth_level) {
                $auth_level = escape($pape_resp->nist_auth_level);
                $success .= "<p>The NIST auth level returned by the " .
                    "server is: <tt>".$auth_level."</tt></p>";
            }

        } else {
                $success .= "<p>No PAPE response was sent by the provider.</p>";
        }

    }

    include './index.php';
}

run();

?>
享受

但丁

注:为了完成OpenID的操作,虽然我用Google解决了我的用户信息/登录数据问题,但我仍然有一个关于Light OpenID的问题。
如果你想帮助我,我们将完全解决OpenID的故事并以之结束。

为了把这个问题从未回答的列表中去掉,我将但丁的答案作为答案发布在这里:

我解决了我的问题。 PHP OpenID中AX的使用示例: 经过两天的研究,我刚刚找到了答案,但谷歌使用AX属性交换而不是SReg来获取更多数据。为什么谷歌总是如此与众不同

但是,stackoverflow应答页中的代码对我不起作用。我的托管服务器返回500个内部服务器错误代码。 所以,我在这里发布了我的代码,它太粗糙了:

oid_ax_common.php

<?php

// Circumnavigate bugs in the GMP math library that can be result in signature
// validation errors
define('Auth_OpenID_BUGGY_GMP', true);

$path_extra = dirname(dirname(dirname(__FILE__)));
$path = ini_get('include_path');
$path = $path_extra . PATH_SEPARATOR . $path;
ini_set('include_path', $path);


function displayError($message) {
    $error = $message;
    include './index.php';
    exit(0);
}

function doIncludes() {
    /**
     * Require the OpenID consumer code.
     */
    require_once "Auth/OpenID/Consumer.php";

    /**
     * Require the "file store" module, which we'll need to store
     * OpenID information.
     */
    require_once "Auth/OpenID/FileStore.php";

    /**
     * Require the Simple Registration extension API.
     */
    //require_once "Auth/OpenID/SReg.php";
    require_once "Auth/OpenID/AX.php";

    /**
     * Require the PAPE extension module.
     */
    require_once "Auth/OpenID/PAPE.php";
}

doIncludes();

global $pape_policy_uris;
$pape_policy_uris = array(
              PAPE_AUTH_MULTI_FACTOR_PHYSICAL,
              PAPE_AUTH_MULTI_FACTOR,
              PAPE_AUTH_PHISHING_RESISTANT
              );

function &getStore() {
    /**
     * This is where the example will store its OpenID information.
     * You should change this path if you want the example store to be
     * created elsewhere.  After you're done playing with the example
     * script, you'll have to remove this directory manually.
     */
    $store_path = null;
    if (function_exists('sys_get_temp_dir')) {
        $store_path = sys_get_temp_dir();
    }
    else {
        if (strpos(PHP_OS, 'WIN') === 0) {
            $store_path = $_ENV['TMP'];
            if (!isset($store_path)) {
                $dir = 'C:\Windows\Temp';
            }
        }
        else {
            $store_path = @$_ENV['TMPDIR'];
            if (!isset($store_path)) {
                $store_path = '/tmp';
            }
        }
    }
    $store_path = './tmp/';
    $store_path .= DIRECTORY_SEPARATOR . '_php_consumer_test';

    if (!file_exists($store_path) &&
        !mkdir($store_path)) {
        print "Could not create the FileStore directory '$store_path'. ".
            " Please check the effective permissions.";
        exit(0);
    }
    $r = new Auth_OpenID_FileStore($store_path);

    return $r;
}

function &getConsumer() {
    /**
     * Create a consumer object using the store object created
     * earlier.
     */
    $store = getStore();
    $r = new Auth_OpenID_Consumer($store);
    return $r;
}

function getScheme() {
    $scheme = 'http';
    if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') {
        $scheme .= 's';
    }
    return $scheme;
}

function getReturnTo() {
    return sprintf("%s://%s:%s%s/oid_ax_receive.php",
                   getScheme(), $_SERVER['SERVER_NAME'],
                   $_SERVER['SERVER_PORT'],
                   dirname($_SERVER['PHP_SELF']));
}

function getTrustRoot() {
    return sprintf("%s://%s:%s%s/",
                   getScheme(), $_SERVER['SERVER_NAME'],
                   $_SERVER['SERVER_PORT'],
                   dirname($_SERVER['PHP_SELF']));
}

?>
oid_ax_send.php

<?php

require_once "oid_ax_common.php";
// Starts session (needed for YADIS)
session_start();

function getOpenIDURL() {
    // Render a default page if we got a submission without an openid
    // value.
    if (empty($_GET['openid_identifier'])) {
        $error = "Expected an OpenID URL.";
        include './index.php';
        exit(0);
    }

    return $_GET['openid_identifier'];
}

function run() {
    // https://www.google.com/accounts/o8/id
    // $openid = 'http://openid-provider.appspot.com/';
    $openid = 'https://www.google.com/accounts/o8/id';
    // $openid .= getOpenIDURL();
    $consumer = getConsumer();

    // Begin the OpenID authentication process.
    $auth_request = $consumer->begin($openid);

    // Create attribute request object
    // See http://code.google.com/apis/accounts/docs/OpenID.html#Parameters for parameters
    // Usage: make($type_uri, $count=1, $required=false, $alias=null)
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/contact/email',2,1, 'email');
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/first',1,1, 'firstname');
    $attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/last',1,1, 'lastname');

    // Create AX fetch request
    $ax = new Auth_OpenID_AX_FetchRequest;

    // Add attributes to AX fetch request
    foreach($attribute as $attr){
        $ax->add($attr);
    }

    // Add AX fetch request to authentication request
    $auth_request->addExtension($ax);

    // No auth request means we can't begin OpenID.
    if (!$auth_request) {
        displayError("Authentication error; not a valid OpenID.");
    }

    /* $sreg_request = Auth_OpenID_SRegRequest::build(
                                     // Required
                                     array('nickname'),
                                     // Optional
                                     array('fullname', 'email'));

    if ($sreg_request) {
        $auth_request->addExtension($sreg_request);
    } */

    $policy_uris = null;
    if (isset($_GET['policies'])) {
        $policy_uris = $_GET['policies'];
    }

    $pape_request = new Auth_OpenID_PAPE_Request($policy_uris);
    if ($pape_request) {
        $auth_request->addExtension($pape_request);
    }

    // Redirect the user to the OpenID server for authentication.
    // Store the token for this authentication so we can verify the
    // response.

    // For OpenID 1, send a redirect.  For OpenID 2, use a Javascript
    // form to send a POST request to the server.
    if ($auth_request->shouldSendRedirect()) {
        $redirect_url = $auth_request->redirectURL(getTrustRoot(),
                                                   getReturnTo());

        // If the redirect URL can't be built, display an error
        // message.
        if (Auth_OpenID::isFailure($redirect_url)) {
            displayError("Could not redirect to server: " . $redirect_url->message);
        } else {
            // Send redirect.
            header("Location: ".$redirect_url);
        }
    } else {
        // Generate form markup and render it.
        $form_id = 'openid_message';
        $form_html = $auth_request->htmlMarkup(getTrustRoot(), getReturnTo(),
                                               false, array('id' => $form_id));

        // Display an error if the form markup couldn't be generated;
        // otherwise, render the HTML.
        if (Auth_OpenID::isFailure($form_html)) {
            displayError("Could not redirect to server: " . $form_html->message);
        } else {
            print $form_html;
        }
    }
}

run();

?>
oid_ax_receive.php

<?php

require_once "oid_ax_common.php";
// Starts session (needed for YADIS)
session_start();

function escape($thing) {
    return htmlentities($thing);
}

function run() {
    $consumer = getConsumer();

    // Complete the authentication process using the server's
    // response.
    $return_to = getReturnTo();
    $response = $consumer->complete($return_to);

    // Check the response status.
    if ($response->status == Auth_OpenID_CANCEL) {
        // This means the authentication was cancelled.
        $msg = 'Verification cancelled.';
    } else if ($response->status == Auth_OpenID_FAILURE) {
        // Authentication failed; display the error message.
        $msg = "OpenID authentication failed: " . $response->message;
    } else if ($response->status == Auth_OpenID_SUCCESS) {
        // Get registration informations
        $ax = new Auth_OpenID_AX_FetchResponse();
        $obj = $ax->fromSuccessResponse($response);

        // Print me raw
        echo '<pre>';
        print_r($obj->data);
        echo '</pre>';
        exit;

        $pape_resp = Auth_OpenID_PAPE_Response::fromSuccessResponse($response);

        if ($pape_resp) {
            if ($pape_resp->auth_policies) {
                $success .= "<p>The following PAPE policies affected the authentication:</p><ul>";

                foreach ($pape_resp->auth_policies as $uri) {
                    $escaped_uri = escape($uri);
                    $success .= "<li><tt>$escaped_uri</tt></li>";
                }

                $success .= "</ul>";
            } else {
                $success .= "<p>No PAPE policies affected the authentication.</p>";
            }

            if ($pape_resp->auth_age) {
                $age = escape($pape_resp->auth_age);
                $success .= "<p>The authentication age returned by the " .
                    "server is: <tt>".$age."</tt></p>";
            }

            if ($pape_resp->nist_auth_level) {
                $auth_level = escape($pape_resp->nist_auth_level);
                $success .= "<p>The NIST auth level returned by the " .
                    "server is: <tt>".$auth_level."</tt></p>";
            }

        } else {
                $success .= "<p>No PAPE response was sent by the provider.</p>";
        }

    }

    include './index.php';
}

run();

?>
享受

但丁

注:为了完成OpenID的操作,虽然我用Google解决了我的用户信息/登录数据问题,但我仍然有一个关于Light OpenID的问题。
如果您想帮助我,我们将完全解决并以OpenID故事结束。

感谢您提供的解决方案。你能把它转移到一个答题箱里,让未来的读者能看到原始问题和答案之间的界限吗?在回答自己的问题时,这通常是一个很好的做法。谢谢感谢您提供解决方案。你能把它转移到一个答题箱里,让未来的读者能看到原始问题和答案之间的界限吗?在回答自己的问题时,这通常是一个很好的做法。谢谢