发布于 2015-10-07 10:02:19 | 162 次阅读 | 评论: 0 | 来源: 网络整理
        The Zend_OpenId_Provider is used to implement OpenID
        servers. This chapter provides very basic examples demonstrating how to
        build a working server. However, for implementation of a production OpenID
        server (like www.myopenid.com) you
        may be required to deal with more complex issues.
    
            The following identity includes the code for creating a user account
            using Zend_OpenId_Provider::register. The link element with
            rel="openid.server" points to our own server script. If you
            submit this identity to an OpenID-enabled site, it will perform
            authentication on this server.
        
The code before <html> is just a trick that automatically creates a user account. You wont need such code when using real identities.
例 29.11. The Identity
<?php
define("TEST_SERVER", Zend_OpenId::absoluteURL("example-8.php"));
define("TEST_ID", Zend_OpenId::selfURL());
define("TEST_PASSWORD", "123");
$server = new Zend_OpenId_Provider();
if (!$server->hasUser(TEST_ID)) {
    $server->register(TEST_ID, TEST_PASSWORD);
}
?>
<html><head>
<link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
</head><body>
<?php echo TEST_ID;?>
</body></html>
            
            The following identity server script handles two kinds of requests
            from OpenID-enabled sites (for association and authentication). Both of
            them are handled by the same method
            Zend_OpenId_Provider::handle. The two arguments to
            Zend_OpenId_Provider are URLs of login and trust pages, these
            ask for interaction from the end-user.
        
            On success, the method Zend_OpenId_Provider::handle
            returns a string that should be passed back to the OpenID-enabled site. On
            failure, it returns false - in this example it will return a
            HTTP 403 response. You will get it if you try to open this page by
            web-browser, because it sends a non-OpenID conformed request.
        
例 29.12. Simple Identity Provider
$server = new Zend_OpenId_Provider("example-8-login.php",
                                   "example-8-trust.php");
$ret = $server->handle();
if (is_string($ret)) {
    echo $ret;
} else if ($ret !== true) {
    header('HTTP/1.0 403 Forbidden');
    echo 'Forbidden';
}
            It is a good idea to use a secure connection (HTTPS) for this and especially for the following interactive scripts, to prevent password disclosure.
            The following script implements a login screen for an identity
            server Zend_OpenId_Provider and redirects to this page when a
            required user has not yet logged-in. On this page, users enter a password
            to login.
        
You should use the password "123" that was used during a tricky user registration from an identity script.
            On submit, the script calls Zend_OpenId_Provider::login
            with the accepted end-user's identity and password, then redirects it back
            to the main identity provider's script. On success, the
            Zend_OpenId_Provider::login establishes a session between the
            end-user and the identity-provider and stores the information about
            logged-in user. So, all following requests from the same end-user won't
            require login procedure (even if they come from another OpenID enabled
            web-site).
        
Note that this session is between end-user and identity provider only. OpenID enabled sites know nothing about it.
例 29.13. Simple Login Screen
<?php
$server = new Zend_OpenId_Provider();
if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
    isset($_POST['openid_action']) &&
    $_POST['openid_action'] === 'login' &&
    isset($_POST['openid_identifier']) &&
    isset($_POST['openid_password'])) {
    $server->login($_POST['openid_identifier'],
                   $_POST['openid_password']);
    Zend_OpenId::redirect("example-8.php", $_GET);
}
?>
<html><body>
<form method="post"><fieldset>
<legend>OpenID Login</legend>
<table border=0>
<tr><td>Name:</td><td><input type="text" name="openid_identifier"
value="<?php
echo htmlspecialchars($_GET['openid_identity']);
?>"></td></tr>
<tr><td>Password:</td><td><input type="text"
name="openid_password" value=""></td></tr>
<tr><td> </td><td><input type="submit"
name="openid_action" value="login"></td></tr>
</table></fieldset></form></body></html>
            The fact that the user is logged-in doesn't mean that the authentication must succeed. The user may decide to trust or not to trust particular OpenID enabled sites. The following trust screen allows the end-user to make that choice. This choice may be done only for current requests or "forever". In the last case information about trusted/untrusted sites is stored in an internal database and all following authentication requests from this site will be handled automatically, without user interaction.
例 29.14. Simple Trust Screen
<?php
$server = new Zend_OpenId_Provider();
if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
    isset($_POST['openid_action']) &&
    $_POST['openid_action'] === 'trust') {
    if (isset($_POST['allow'])) {
        if (isset($_POST['forever'])) {
            $server->allowSite($server->getSiteRoot($_GET));
        }
        $server->respondToConsumer($_GET);
    } else if (isset($_POST['deny'])) {
        if (isset($_POST['forever'])) {
            $server->denySite($server->getSiteRoot($_GET));
        }
        Zend_OpenId::redirect($_GET['openid_return_to'],
                              array('openid.mode'=>'cancel'));
    }
}
?>
<html><body>
<p>A site identifying as
<a href="<?php echo htmlspecialchars($server->getSiteRoot($_GET));?>">
<?php echo htmlspecialchars($server->getSiteRoot($_GET));?></a>
has asked us for confirmation that
<a href="<?php echo htmlspecialchars($server->getLoggedInUser());?>">
<?php echo htmlspecialchars($server->getLoggedInUser());?></a>
is your identity URL.</p>
<form method="post">
<input type="checkbox" name="forever">
<label for="forever">forever</label><br>
<input type="hidden" name="openid_action" value="trust">
<input type="submit" name="allow" value="Allow">
<input type="submit" name="deny" value="Deny">
</form></body></html>
            Production OpenID servers usually support Simple Registration Extension that allows consumers to ask some information about user from provider. In this case the trust page is usually extended with ability to enter requested fields or to select user profile.
            It is possible to combine all provider functions in one script. In
            this case login and trust URLs are omitted, and
            Zend_OpenId_Provider assumes that they point to the same page
            with additional "openid.action" GET argument.
        
The following example is not complete. It doesn't provide GUI for end-user like it should, but performs automatic login and trusting instead. It is done just to simplify the example, and real server must include code from previous examples.
例 29.15. All together
$server = new Zend_OpenId_Provider();
define("TEST_ID", Zend_OpenId::absoluteURL("example-9-id.php"));
define("TEST_PASSWORD", "123");
if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
    isset($_GET['openid_action']) &&
    $_GET['openid_action'] === 'login') {
    $server->login(TEST_ID, TEST_PASSWORD);
    unset($_GET['openid_action']);
    Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
} else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
    isset($_GET['openid_action']) &&
    $_GET['openid_action'] === 'trust') {
    unset($_GET['openid_action']);
    $server->respondToConsumer($_GET);
} else {
    $ret = $server->handle();
    if (is_string($ret)) {
        echo $ret;
    } else if ($ret !== true) {
        header('HTTP/1.0 403 Forbidden');
        echo 'Forbidden';
    }
}
            
            If you compare this example with previous example divided to
            separate page, in addition to dispatch code you will see only the one
            difference - unset($_GET['openid_action']). This
            unset is necessary to route next request to main
            handler.
        
The following identity page makes a trick again. It creates new user account and associates it with profile (nickname and password). Such tricks aren't needed in real life where end-user registers on OpenID server and fill-in their profiles, but implementing this GUI is not a subject of this manual.
例 29.16. Identity with Profile
<?php
define("TEST_SERVER", Zend_OpenId::absoluteURL("example-10.php"));
define("TEST_ID", Zend_OpenId::selfURL());
define("TEST_PASSWORD", "123");
$server = new Zend_OpenId_Provider();
if (!$server->hasUser(TEST_ID)) {
    $server->register(TEST_ID, TEST_PASSWORD);
    $server->login(TEST_ID, TEST_PASSWORD);
    $sreg = new Zend_OpenId_Extension_Sreg(array(
        'nickname' =>'test',
        'email' => 'test@test.com'
    ));
    $root = Zend_OpenId::absoluteURL(".");
    Zend_OpenId::normalizeUrl($root);
    $server->allowSite($root, $sreg);
    $server->logout();
}
?>
<html><head>
<link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
</head><body>
<?php echo TEST_ID;?>
</body></html>
            You should pass this identity to OpenID-enabled site (use Simple Registration Extension example from previous chapter) and it will use the following OpenID server script.
            It is a variation from previous "All together" example. It uses the
            same automatic login mechanism, but it doesn't contain any code for trust
            page. The user already trusts "forever" to example scripts. This trust was
            made by Zend_OpenId_Provider::alowSite method in identity
            script. The same method associated profile with trusted URL and this
            profile will be returned automatically on request from this trusted
            URL.
        
            The only thing necessary to make Simple Registration Extension work
            is passing object of Zend_OpenId_Extension_Sreg as second
            argument to Zend_OpenId_Provider::handle.
        
例 29.17. Provider with SREG
$server = new Zend_OpenId_Provider();
$sreg = new Zend_OpenId_Extension_Sreg();
define("TEST_ID", Zend_OpenId::absoluteURL("example-10-id.php"));
define("TEST_PASSWORD", "123");
if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
    isset($_GET['openid_action']) &&
    $_GET['openid_action'] === 'login') {
    $server->login(TEST_ID, TEST_PASSWORD);
    unset($_GET['openid_action']);
    Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
} else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
    isset($_GET['openid_action']) &&
    $_GET['openid_action'] === 'trust') {
   echo "UNTRUSTED DATA" ;
} else {
    $ret = $server->handle(null, $sreg);
    if (is_string($ret)) {
        echo $ret;
    } else if ($ret !== true) {
        header('HTTP/1.0 403 Forbidden');
        echo 'Forbidden';
    }
}
            
            Building OpenID servers is less usual tasks then building
            OpenID-enabled sites, so this manual don't try to cover all
            Zend_OpenId_Provider features as it was done for
            Zend_OpenId_Consumer.
        
In two words in additional it provides:
a set of methods to build end-user's GUI interface that allows users to register, manage their trusted sites and profiles.
                    an abstraction storage layer to store information about users,
                    their sites and profiles. It also stores associations between
                    provider and OpenID-enabled sites. This layer is very similar
                    to the Zend_OpenId_Consumer's one. It also uses
                    file storage by default but may be substituted with another
                    implementation.
                
an abstraction user-association layer that may associate end-user's web browser with logged-in identity
            Zend_OpenId_Provider doesn't try to cover all possible
            features that can be implemented by OpenID server (like digital
            certificates), but it can be easily extended using
            Zend_OpenId_Extensions or by creating a child class.