全部博文(315)
分类:
2008-03-03 10:30:24
简单注册插件
为了认证,OPENID可以使用轻量级的资料交换。该特性并不是由OpenId认证所描述,而是由OPENID简单注册插件协议所规范。该协议允许启用OPENID站点查询一个从OPENID Provider传回的终端用户的信息。
这样的信息可能包含:
1、 别名――任何终端用户想使用的一串UTF-8的字符串作为别名
2、 邮件――由RFC2822的3.4.1章节所规范的终端用户邮件地址
3、 全名――一串表示终端用户全名的UTF-8字符串
4、 出生日期(DATE OF BIRTH-DOB)――以YYYY-MM-DD为格式的终端用户出生日期。如果标识该日期的值少于指定数字则用0来填充。这些值的长度总为十进位。如果没有指定则设为0。比如只设定年份1980,则该值为“1980-00-00”
5、 Gender――性别
6、 Postcode――邮编
7、 Country――国家
8、 Language――语言
9、 Timezone――时区
一个启用OPENID的网络站点可能会要求这些字段的综合。它也可能严格的需要一些信息,并且允许用户提供和隐藏其他的信息。下面一个例子就是创建一个Zend_OpenId_Extension_Sreg类的对象需要一个别名,以及可选的email和全名。
require_once "Zend/OpenId/Consumer.php";
require_once "Zend/OpenId/Extension/Sreg.php";
$sreg = new Zend_OpenId_Extension_Sreg(array(
'nickname'=>true,
'email'=>false,
'fullname'=>false), null, 1.1);
$consumer = new Zend_OpenId_Consumer();
if (!$consumer->login($_POST['openid_identifier'], 'example-6_3.php', null, $sreg)) {
die("OpenID login failed.");
}
正如你所看到的Zend_OpenId_Extension_Sreg构造器接收一个所需字段的数组。该数组以字段名为其索引,所需标签为其值。True标识该字段是必须的,false则标示该字段是可选的。Zend_OpenId_Consumer::login接受该插件或是插件列表为其第四个参数。
作为认证的第三步,Zend_OpenId_Extension_Sreg对象应该传值给Zend_OpenId_Consumer::verify。成功认证后Zend_OpenId_Extension_Sreg::getProperties将返回一个请求字段的关联数组。
require_once "Zend/OpenId/Consumer.php";
require_once "Zend/OpenId/Extension/Sreg.php";
$sreg = new Zend_OpenId_Extension_Sreg(array(
'nickname'=>true,
'email'=>false,
'fullname'=>false), null, 1.1);
$consumer = new Zend_OpenId_Consumer();
if ($consumer->verify($_GET, $id, $sreg)) {
echo "VALID $id
\n";
$data = $sreg->getProperties();
if (isset($data['nickname'])) {
echo "nickname: " . $data['nickname'] . "
\n";
}
if (isset($data['email'])) {
echo "email: " . $data['email'] . "
\n";
}
if (isset($data['fullname'])) {
echo "fullname: " . $data['fullname'] . "
\n";
}
} else {
echo "INVALID $id";
}
如果Zend_OpenId_Extension_Sreg创建时没有带任何参数,用户代码会校验所需数据是否存在。然而,如果它创建时带了同样的所需字段列表,它也将会自动校验所需数据是否存在。在上例中,如果丢失了任何所需的字段,Zend_OpenId_Consumer::verify将返回false。
缺省情况下,Zend_OpenId_Extension_Sreg使用http1.0,因为1.1尚未定案。但有些服务器所请求的SREG名称空间里只支持1.1。这样你就必须在中Zend_OpenId_Extension_Sreg特定的设定为1.1的版本。
第二个Zend_OpenId_Extension_Sreg构造器的参数是一个规范URL,一般由标识Provider所提供。
与Zend_Auth集成
Zend Framework提供了一个特别的类用来做用户认证――Zend_Auth。该类可以与Zend_OpenId_Consumer一起使用。下面的例子显示了OpenIdAdapter怎样实现Zend_Auth_Adapter_Interface的认证方法。它发起了一个认证的查询和校验。
这个adapter与已经存在的Adapter最大的不同就是,它针对两个HTTP的请求,并且包含了一个指派码来进行第二步和第三步的OPENID认证。
require_once "Zend/OpenId/Consumer.php";
require_once "Zend/Auth.php";
require_once "Zend/Auth/Adapter/Interface.php";
class OpenIdAdapter implements Zend_Auth_Adapter_Interface {
private $_id = null;
public function __construct($id = null) {
$this->_id = $id;
}
public function authenticate() {
$id = $this->_id;
if (!empty($id)) {
$consumer = new Zend_OpenId_Consumer();
if (!$consumer->login($id)) {
$ret = false;
$mdg = "Authentication failed.";
}
} else {
$consumer = new Zend_OpenId_Consumer();
if ($consumer->verify($_GET, $id)) {
$ret = true;
$msg = "Authentication successful";
} else {
$ret = false;
$msg = "Authentication failed";
}
}
return new Zend_Auth_Result($ret, $id, array($msg));
}
}
$status = "";
$auth = Zend_Auth::getInstance();
if ((isset($_POST['openid_action']) &&
$_POST['openid_action'] == "login" &&
!empty($_POST['openid_identifier'])) ||
isset($_GET['openid_mode'])) {
$adapter = new OpenIdAdapter(@$_POST['openid_identifier']);
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
Zend_OpenId::redirect(Zend_OpenId::selfURL());
} else {
$auth->clearIdentity();
foreach ($result->getMessages() as $message) {
$status .= "$message
\n";
}
}
} else if ($auth->hasIdentity()) {
if (isset($_POST['openid_action']) &&
$_POST['openid_action'] == "logout") {
$auth->clearIdentity();
} else {
$status = "Yoy are logged-in as " . $auth->getIdentity() . "
\n";
}
}
?>
echo "$status";?>
使用Zend_Auth将终端用户的标识保存进了session的数据。它可以由Zend_Auth::hasIdentity和Zend_Auth::getIdentity进行查询。
与Zend_Controller进行集成
最后的一些话是关于与M-V-C应用程序的集成。比如ZF应用程序是使用Zend_Controller类来实现,他们使用Zend_Controller_Response_Http类的对象来准备HTTP的响应并且发送它们到终端用户的浏览器。
Zend_OpenId_Consumer并没有提供任何GUI的能力但它在Zend_OpenId_Consumer::login和Zend_OpenId_Consumer::check成功后会发起HTTP的重定向。这些重定向如果已经被传送给了浏览器,也许不会正确的工作甚至根本不工作。为了正确的发起以MVC代码方式的重定向,真实的Zend_Controller_Response_Http应该被传送给Zend_OpenId_Consumer::login或者Zend_OpenId_Consumer::check作为最后一个参数。