标签: zendframework2.0用户身份验证 |
分类:ZendFramework2 |
先介绍下我的Demo的组织方式,方便大家理解(ZF2的文件夹的组织形式我是上网下别人的),其中红色的为本例操作中会修改的文件:
+ MyTest(我的工程文件夹,放在apache2\htdocs目录下)
|-application(是空文件夹)
|+config
| | +autoload(里面有global.cofig.php,没涉及到)
| |application.config.php(用于配置modules,路径等参数)
| +module
| | +Application (这就是一个module,在这个工程里对应的就是首页,可以直接把登陆的写在这里面)
| | +Test (我的登陆是写在这个module里)
| | | +config
| | | module.config.php (用来配置module的di等)
| | +src
| | | +Test
| | | +Controller
| | | | AdminController.php (这个就是登陆用到的控制器)
| | | | TestController.php (这个是用来显示登陆后的信息)
| | | +Model
| | +view (这是存放显示文件,这里就不再展开了)
|+public
| | +css
| | +images
| | +js
| | .htaccess
| | index.php (应用程序的入口文件)
|+vendor
| +ZendFramework
| | +library
| +MyTest (放一些插件文件)
| | +Acl
| | | Navigation.php (Acl进行验证的初始化类,后面会具体讲到)
| | +Controller
| | | +Plugin
| | | Acl.php (Acl插件)
| +Zend (Zend 2.0.3Beta库)
2.Zend\Authentication库
这个库的作用主要是用于将用户录入的个人信息与数据库进行比较,判断用户是否为已注册用户,从而确定其身份,同时可将登陆的用户信息存入SESSION中(对SESSION不了解的可以上网搜索),用户跳到别的页面中时,其登陆信息依然存在。
Zend\Authentication库文件的主要目录有:
+ Zend
|+Authentication
| +Adapter
| | DbTable.php
| +Exception
| +Storage
| AuthenticationService.php
| Result.php
当然这些可以自己写数据库操作代码实现,但ZF的类能帮助我们更快速、方便地进行开发。
使用Authentication进行用户身份验证时,我主要用Adapter\DbTable进行数据库的连接,使用AuthenticationSerivce类和Result类进行验证操作,因此你需要在登陆控制器类中(我这里为AdminController.php)添加如下代码:
Code2.1.
useZend\Authentication\Adapter, //使用命名空间,2.0中新增的功能,方便大型网站的开发
Zend\Authentication,
Zend\Authentication\Result;
然后在AdminController.php的loginAction()中加入如下代码:
Code 2.2.
... //获取用户提交的信息,并判断有效性
if($form->isValid($formData)) //若有效
{
// 获取表单的数据
$adminName = $form->getValue('adminName'); //adminName为用户名表单的name值,即name="adminName"
$password= $form->getValue('password'); //password为密码表单的name值
// 通过数据库获取authAdapter,这里的$this->adminTable->getAdapter()是我自定义的函数,主要是输入一个adapter参数,可参考Zend\Db\Adapter获取adapter的方法,这里不再细说了
$authAdapter= new\Zend\Authentication\Adapter\DbTable($this->adminTable->getAdapter(),
'admin', // 数据库中存放注册信息的表的名称
'admin_name', // 表中存放用户名的字段
'password' // 表中存放密码的字段
'md5(?)'); //是否对密码进行MD5编码,这里我没选,直接用明码
// 将用户名和密码进行验证
$authAdapter->setIdentity($adminName)->setCredential($password);
$auth = new \Zend\Authentication\AuthenticationService();
$result =$auth->authenticate($authAdapter);
if($result->isValid())
{
// storing in the session
$auth->getStorage()->write((object)array('adminName'=> $adminName,
'password' => $password,
'role' =>...//这里可保存role值,后面的Acl会用到,role值可存在database文件或.ini文件中
));
// 跳转到显示信息页面
return$this->redirect()->toRoute('default',array('controller' => 'test',
'action' => 'index'));
}
else
{
// 虽然这里我显示了错误信息,但这里面我还不知道如何在VIEW里显示
switch($result->getCode())
{
case Result::FAILURE_IDENTITY_NOT_FOUND:
$errorMessage = "Admin name isn't exist!";
break;
case Result::FAILURE_CREDENTIAL_INVALID:
$errorMessage = "Your password is wrong!";
break;
default:
$errorMessage = "There are some mistakes when login!";
}
// 停留在注册页,就是这里,需改将参数回传
return$this->redirect()->toRoute('default',array('controller' => 'admin',
'action' => 'login'));
}
}
之后,如果你想知道是否已经登陆,在相应的Action里加上判断即可:
Code 2.3.
public functionexampleAction()
{
$auth = new AuthenticationService(); //获取实例化Zend\AuthenticationService对象
if($auth->hasIdentity()) //判断是否登陆,是,则记录登陆信息
{
$user =$auth->getIdentity();
}
}
至此,ZendFramework2.0.3中通过Zend\Authentication进行登陆操作的代码结束了,其操作还是比较简单的。
3.Zend\Acl库实现用户权限的控制
Zend\Acl的权限控制主要包括角色定义,资源定义以及制作黑白名单几部分,下面是Acl库文件的主要目录:
+ Zend
|+Acl
| +Assertion
| +Exception
| +Resource
|| GenericResource.php
| +Role
|| GenericRole.php
| Acl.php
接下来就是要为MyTest工程添加角色和资源,方法就是在最上面的目录里的Navigation.php定义一个继承自Acl的类--Navigation:
Code 3.1.
// 添加命名空间
namespace MyTest\Acl;
use Zend\Acl\Role\GenericRole,
Zend\Acl\Resource\GenericResource,
Zend\Acl\Acl;
class Navigation extendsAcl
{
public function __construct()
{
// 添加了三种角色guest, user, admin,如user的父类是guest,因此它继承了guest的所有权限
$this->addRole(newGenericRole('guest'));
$this->addRole(new GenericRole('user'),'guest');
$this->addRole('admin','user');
// 添加资源,这里以'application' module, 'index'controller, 'index' action为例
$this->addResource(newGenericResource('Application'));
$this->addResource(newGenericResource('Application.index'),'Application');
$this->addResource(newGenericResource('Application.index.index'),'Application');
// 以'test'module, 'test' controller为例
$this->addResource(newGenericResource('aTest'));
$this->addResource(new GenericResource('Test.test'),'Test');
...
// 添加白名单,资源必须与上面的对应
$this->allow('guest','Application.index.index');
$this->allow('user','Application.index.index');
$this->allow('user', 'Test.test');
$this->allow('admin'); //允许管理员所有权限
}
}
之后,你只需要在相应的Action里实例化这个对象,然后进行判断是否被允许访问相应资源即可,比如我是在TestController.php的indexAction()里添加如下代码的:
Code 3.2.
//相应的命名空间
use Zend\Authentication\AuthenticationService,
Zend\Authentication,
MyTest\Acl;
// 初始化角色为游客,并获取角色
$role ='guest';
$auth = newAuthenticationService();
if($auth->hasIdentity())
{
$user =$auth->getIdentity();
$role = $user->role; //role值在前面必须存入session中,不然这里会出错
}
$allowed =false;
$acl = new\MyTest\Acl\Navigation();
//checking if the roles have right to access
if($acl->isAllowed($role,'test', 'index'))
{
$allowed = true;
}
if(!$allowed)
{
//返回到登陆页
return$this->redirect()->toRoute('default',array(
'controller' =>'admin',
'action' =>'login',
));
}
到这里,Zend\Authentication与Zend\Acl结合的用户身份验证的操作都全部完成了,但有一个的麻烦的地方就是用这里的代码,在判断每个页面是否能被访问时,都需要在相应的Action里添加Code3.3.的判断代码,显然非常地不方便,实际上好像可以用插件实现