我的实现:
问题 #1
class App_Model_Acl extends Zend_Acl
{
const ROLE_GUEST = 'guest';
const ROLE_USER = 'user';
const ROLE_PUBLISHER = 'publisher';
const ROLE_EDITOR = 'editor';
const ROLE_ADMIN = 'admin';
const ROLE_GOD = 'god';
protected static $_instance;
protected function __construct()
{
$this->addRole(new Zend_Acl_Role(self::ROLE_GUEST));
$this->addRole(new Zend_Acl_Role(self::ROLE_USER), self::ROLE_GUEST);
$this->addRole(new Zend_Acl_Role(self::ROLE_PUBLISHER), self::ROLE_USER);
$this->addRole(new Zend_Acl_Role(self::ROLE_EDITOR), self::ROLE_PUBLISHER);
$this->addRole(new Zend_Acl_Role(self::ROLE_ADMIN), self::ROLE_EDITOR);
$this->addRole(new Zend_Acl_Role(self::ROLE_GOD));
$this->allow(self::ROLE_GOD);
$this->add(new Zend_Acl_Resource('mvc:users'))
->add(new Zend_Acl_Resource('mvc:users.auth'), 'mvc:users')
->add(new Zend_Acl_Resource('mvc:users.list'), 'mvc:users');
$this->allow(null, 'mvc:users', array('index', 'list'));
$this->allow('guest', 'mvc:users.auth', array('index', 'login'));
$this->allow('guest', 'mvc:users.list', array('index', 'list'));
$this->deny(array('user'), 'mvc:users.auth', array('login'));
$moduleResource = new Zend_Acl_Resource('mvc:snippets');
$this->add($moduleResource)
->add(new Zend_Acl_Resource('mvc:snippets.crud'), $moduleResource)
->add(new Zend_Acl_Resource('mvc:snippets.list'), $moduleResource);
$this->allow(null, $moduleResource, array('index', 'list'));
$this->allow('user', 'mvc:snippets.crud', array('create', 'update', 'delete', 'read', 'list'));
$this->allow('guest', 'mvc:snippets.list', array('index', 'list'));
return $this;
}
protected static $_user;
public static function setUser(Users_Model_User $user = null)
{
if (null === $user) {
throw new InvalidArgumentException('$user is null');
}
self::$_user = $user;
}
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public static function resetInstance()
{
self::$_instance = null;
self::getInstance();
}
}
class Smapp extends Bootstrap // class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected static $_currentUser;
public function __construct($application)
{
parent::__construct($application);
}
public static function setCurrentUser(Users_Model_User $user)
{
self::$_currentUser = $user;
}
public static function getCurrentUser()
{
if (null === self::$_currentUser) {
self::setCurrentUser(Users_Service_User::getUserModel());
}
return self::$_currentUser;
}
public static function getCurrentUserId()
{
$user = self::getCurrentUser();
return $user->getId();
}
}
在
class bootstrap
中。
protected function _initUser()
{
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
if ($user = Users_Service_User::findOneByOpenId($auth->getIdentity())) {
$userLastAccess = strtotime($user->last_access);
if ((time() - $userLastAccess) > 60*5) {
$date = new Zend_Date();
$user->last_access = $date->toString('YYYY-MM-dd HH:mm:ss');
$user->save();
}
Smapp::setCurrentUser($user);
}
}
return Smapp::getCurrentUser();
}
protected function _initAcl()
{
$acl = App_Model_Acl::getInstance();
Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($acl);
Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole(Smapp::getCurrentUser()->role);
Zend_Registry::set('Zend_Acl', $acl);
return $acl;
}
以及Front_Controller_Plugin
class App_Plugin_Auth extends Zend_Controller_Plugin_Abstract
{
private $_identity;
private $_acl;
private $_noacl = array('module' => 'admin',
'controller' => 'error',
'action' => 'no-auth');
private $_noauth = array('module' => 'users',
'controller' => 'auth',
'action' => 'login');
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$this->_identity = Smapp::getCurrentUser();
$this->_acl = App_Model_Acl::getInstance();
if (!empty($this->_identity)) {
$role = $this->_identity->role;
} else {
$role = null;
}
$controller = $request->controller;
$module = $request->module;
$controller = $controller;
$action = $request->action;
$moduleLevel = 'mvc:'.$module;
$controllerLevel = $moduleLevel . '.' . $controller;
$privelege = $action;
if ($this->_acl->has($controllerLevel)) {
$resource = $controllerLevel;
} else {
$resource = $moduleLevel;
}
if ($module != 'default' && $controller != 'index') {
if ($this->_acl->has($resource) && !$this->_acl->isAllowed($role, $resource, $privelege)) {
if (!$this->_identity) {
$request->setModuleName($this->_noauth['module']);
$request->setControllerName($this->_noauth['controller']);
$request->setActionName($this->_noauth['action']);
} else {
$request->setModuleName($this->_noacl['module']);
$request->setControllerName($this->_noacl['controller']);
$request->setActionName($this->_noacl['action']);
}
throw new Exception('Access denied. ' . $resource . '::' . $role);
}
}
}
}
最后,Auth_Controller诞生啦 :)
class Users_AuthController extends Smapp_Controller_Action
{
protected $_storage;
public function getStorage()
{
if (null === $this->_storage) {
$this->_storage = new Zend_Session_Namespace(__CLASS__);
}
return $this->_storage;
}
public function indexAction()
{
return $this->_forward('login');
}
public function loginAction()
{
$openId = null;
if ($this->getRequest()->isPost() and $openId = ($this->_getParam('openid_identifier', false))) {
} elseif (!isset($_GET['openid_mode'])) {
return;
}
$userService = new Users_Service_User();
$result = $userService->authenticate($openId, $this->getResponse());
if ($result->isValid()) {
$identity = $result->getIdentity();
if (!$identity['Profile']['display_name']) {
return $this->_helper->redirector->gotoSimpleAndExit('update', 'profile');
}
$this->_redirect('/');
} else {
$this->view->errorMessages = $result->getMessages();
}
}
public function logoutAction()
{
$auth = Zend_Auth::getInstance();
$auth->clearIdentity();
$this->_redirect('/');
}
}
问题 #2
将其放在Zend_Auth
内部。
验证成功后,将身份写入存储。 $auth->getStorage()->write($result->getIdentity());
identity
- 简单地表示user_id
数据库设计
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`open_id` varchar(255) NOT NULL,
`role` varchar(20) NOT NULL,
`last_access` datetime NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `open_id` (`open_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `user_profile` (
`user_id` bigint(20) NOT NULL,
`display_name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`real_name` varchar(100) DEFAULT NULL,
`website_url` varchar(255) DEFAULT NULL,
`location` varchar(100) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`about_me` text,
`view_count` int(11) NOT NULL DEFAULT '0',
`updated_at` datetime NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
一些糖
class Smapp_View_Helper_IsAllowed extends Zend_View_Helper_Abstract
{
protected $_acl;
protected $_user;
public function isAllowed($resource = null, $privelege = null)
{
return (bool) $this->getAcl()->isAllowed($this->getUser(), $resource, $privelege);
}
public function getAcl()
{
if (null === $this->_acl) {
$this->setAcl(App_Model_Acl::getInstance());
}
return $this->_acl;
}
public function setAcl(Zend_Acl $acl)
{
$this->_acl = $acl;
return $this;
}
public function getUser()
{
if (null === $this->_user) {
$this->setUser(Smapp::getCurrentUser());
}
return $this->_user;
}
public function setUser(Users_Model_User $user)
{
$this->_user = $user;
return $this;
}
}
对于任何视图脚本中的这种事情
<?php if ($this->isAllowed('mvc:snippets.crud', 'update')) : ?>
<a title="Edit «<?=$this->escape($snippetInfo['title'])?>» snippet">Edit</a>
<?php endif?>
有问题?:)