- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
上下文:
我的问题与我正在开发的论坛非常相似,其中有:
我希望此 ACL 在整个站点范围内应用,并且默认情况下拒绝所有资源。
我阅读了使用 Zend_Acl 的基础知识 - 基本上是创建角色( guest 、成员、管理员)并拒绝或允许这些角色的资源( Controller 、方法)。该文档并没有具体说明您应该如何在您的应用程序中实际实现 acl 代码,所以我继续查看 SO..
遇到一个非常有用的 stackoverflow answer from marek这阐明了这个问题,但是由于我不熟悉,我仍然无法完全理解如何在考虑最佳实践的情况下正确实现这一点。
张贴者在应用程序根目录中有一个静态文件 configAcl.php
,它初始化 acl 对象、添加角色、从每个 Controller 创建资源、授予 admin
访问权限对所有内容,授予对除管理员以外的所有内容的正常
访问权限,并将 acl 对象存储在注册表中供以后使用。
$acl = new Zend_Acl();
$roles = array('admin', 'normal');
// Controller script names. You have to add all of them if credential check
// is global to your application.
$controllers = array('auth', 'index', 'news', 'admin');
foreach ($roles as $role) {
$acl->addRole(new Zend_Acl_Role($role));
}
foreach ($controllers as $controller) {
$acl->add(new Zend_Acl_Resource($controller));
}
// Here comes credential definiton for admin user.
$acl->allow('admin'); // Has access to everything.
// Here comes credential definition for normal user.
$acl->allow('normal'); // Has access to everything...
$acl->deny('normal', 'admin'); // ... except the admin controller.
// Finally I store whole ACL definition to registry for use
// in AuthPlugin plugin.
$registry = Zend_Registry::getInstance();
$registry->set('acl', $acl);
问题 #1 - 这段代码应该放在 Bootstrap 中,还是放在像这样的独立文件中?如果是的话,如果它在图书馆目录里面会更好吗?
它的第二部分是一个扩展 Zend Controller Plugin Abstract 类的新类,允许它挂接到 auth/login
,逻辑基本上是如果登录失败,它会重定向..否则它会从注册表中获取 acl 对象,获取身份,并确定是否允许用户查看此资源。
$identity = $auth->getIdentity();
$frontController->registerPlugin(new AuthPlugin());
问题 #2 - 我应该如何准确地编写实际返回用户身份的 auth 插件部分?我意识到他在下面有一些代码生成了一个 Auth 适配器数据库表对象,该对象将按用户 ID 和凭据(散列通过检查)查询数据库表的列。我对它与 getIdentity 部分的配合感到困惑。
假设我的用户表由以下数据组成:
user_id user_name level
1 superadmin 3
2 john 2
3 example.com 1
其中级别 3 = 管理员,2 = 成员,1 = 访客。
问题 #3 - 放置上述授权码的确切位置在哪里?在登录 Controller 内部?
问题 #4 - 另一张海报 replies在他关于如何在模型内部完成 acl 逻辑的文章中,但是他使用的特定方法不受本地支持并且需要解决方法,这可行吗?理想情况下真的应该这样做吗?
最佳答案
我的实现:
问题 #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;
/* Singleton pattern */
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);
//unique role for superadmin
$this->addRole(new Zend_Acl_Role(self::ROLE_GOD));
$this->allow(self::ROLE_GOD);
/* Adding new resources */
$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'));
/* Adding new resources */
$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;
}
/**
*
* @return App_Model_Acl
*/
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
{
/**
* @var App_Model_User
*/
protected static $_currentUser;
public function __construct($application)
{
parent::__construct($application);
}
public static function setCurrentUser(Users_Model_User $user)
{
self::$_currentUser = $user;
}
/**
* @return App_Model_User
*/
public static function getCurrentUser()
{
if (null === self::$_currentUser) {
self::setCurrentUser(Users_Service_User::getUserModel());
}
return self::$_currentUser;
}
/**
* @return App_Model_User
*/
public static function getCurrentUserId()
{
$user = self::getCurrentUser();
return $user->getId();
}
}
在类引导
protected function _initUser()
{
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
if ($user = Users_Service_User::findOneByOpenId($auth->getIdentity())) {
$userLastAccess = strtotime($user->last_access);
//update the date of the last login time in 5 minutes
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;
/**
* the acl object
*
* @var zend_acl
*/
private $_acl;
/**
* the page to direct to if there is a current
* user but they do not have permission to access
* the resource
*
* @var array
*/
private $_noacl = array('module' => 'admin',
'controller' => 'error',
'action' => 'no-auth');
/**
* the page to direct to if there is not current user
*
* @var unknown_type
*/
private $_noauth = array('module' => 'users',
'controller' => 'auth',
'action' => 'login');
/**
* validate the current user's request
*
* @param zend_controller_request $request
*/
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;
//go from more specific to less specific
$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']);
//$request->setParam('authPage', 'login');
} else {
$request->setModuleName($this->_noacl['module']);
$request->setControllerName($this->_noacl['controller']);
$request->setActionName($this->_noacl['action']);
//$request->setParam('authPage', 'noauth');
}
throw new Exception('Access denied. ' . $resource . '::' . $role);
}
}
}
}
最后 - Auth_Controller` :)
class Users_AuthController extends Smapp_Controller_Action
{
//sesssion
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))) {
//do nothing
} elseif (!isset($_GET['openid_mode'])) {
return;
}
//$userService = $this->loadService('User');
$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();
//Zend_Session::destroy();
$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;
一些糖
/**
* SM's code library
*
* @category
* @package
* @subpackage
* @copyright Copyright (c) 2009 Pavel V Egorov
* @author Pavel V Egorov
* @link http://epavel.ru/
* @since 08.09.2009
*/
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);
}
/**
* @return App_Model_Acl
*/
public function getAcl()
{
if (null === $this->_acl) {
$this->setAcl(App_Model_Acl::getInstance());
}
return $this->_acl;
}
/**
* @return App_View_Helper_IsAllowed
*/
public function setAcl(Zend_Acl $acl)
{
$this->_acl = $acl;
return $this;
}
/**
* @return Users_Model_User
*/
public function getUser()
{
if (null === $this->_user) {
$this->setUser(Smapp::getCurrentUser());
}
return $this->_user;
}
/**
* @return App_View_Helper_IsAllowed
*/
public function setUser(Users_Model_User $user)
{
$this->_user = $user;
return $this;
}
}
对于任何 View 脚本中的类似情况
<?php if ($this->isAllowed('mvc:snippets.crud', 'update')) : ?>
<a title="Edit «<?=$this->escape($snippetInfo['title'])?>» snippet">Edit</a>
<?php endif?>
问题? :)
关于php - 实用的 Zend_ACL + Zend_Auth 实现和最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2046608/
我的目标是要求某些页面登录。我正在使用 Zend Framework MVC,我正在尝试寻找有关最佳实践的示例。 关于我正在寻找的东西的一些注释: 我希望未登录的用户获得一个登录框,然后在通过身份验证
我尝试使用: // do login if request is posted if (isset($_POST) && !empty($_POST)) { // do authencatio
我使用 Zend_Auth 和 setCredentialTreatment 来设置散列方法和盐。我看到所有示例都在做类似的事情,其中 salt 似乎作为文本插入。 ->setCredential
我还遇到了另一个关于 Zend 的奇怪烦人的事情。 基本上,我在创建用户域后有以下代码: $this->auth = Zend_Auth::getInstance(); $this->view->us
这很简单。我写的 $auth->getStorage()->write($user); 然后我想在一个单独的过程中加载这个 $user,但我不能,因为 $user = $auth->getIdenti
我想创建 Zend_Auth 的多个实例上课,因为我有两个模块 管理员 前台 发生的事情是当我登录管理员时,它会自动登录 正面或反之。 我想要的是在同时认证后分别在两个模块中工作。 最佳答案 Zend
谁知道为什么我的Zend_Auth在特定时间到期,我该如何设置/延长它? 最佳答案 $seconds = 3600; //one hour $namespace = new Zend_Session_
我正在处理我在 Zend Framework 中的第一次用户登录,但我对 Zend_Auth 有点困惑。我阅读的所有关于它的文章都直接在 Controller 中使用它。但对我来说,作为插件工作更有意
给专业人士的一个简短问题。 是否可以将 Zend_Auth_Adapter_DbTable 与 ZendX_Db_Adapter 一起使用? 我试过这个: $adapter = new Zend_Au
我使用 Zend_Auth 来验证用户,然后将他们的详细信息存储在默认的 Zend_Auth session 中。这意味着当用户编辑他的详细信息时,这些更改不会反射(reflect)在应用程序中,直到
专家, 我刚刚发现 Zend_Auth 的一个奇怪行为,即它无法在服务器中存储 session 。我所有使用 Zend_Auth 进行身份验证的现有应用程序都会突然发生这种情况,所以我确定代码没有问题
有没有办法让 Zend_Auth 接受不区分大小写的身份(即用户名)? Zend_Auth 似乎提供了一种方法来为凭证字段添加特殊处理,但不为身份字段添加特殊处理。 PS:我正在使用指向 Postgr
我正在使用一个简单的 Zend_Auth设置为我的一个应用程序验证用户,使用 controller plugin 中的 preDispatch() 方法检查.当匿名用户导航到 /users/view/
当我的用户登录时,我会在 UI 上显示他们的详细信息(姓名、电子邮件)。当他们更新个人资料时,我想显示更新的详细信息,而不需要用户注销并重新登录。 UI 详细信息通过 View 助手从 Zend_Au
我将如何全局保护我的所有 Controller (我的登录 Controller 除外)以确保我的应用程序在所有点都是安全的(没有隐藏的 ajax 调用后门等)。我想我可以把它放在我的 Bootstr
上下文: 我的问题与我正在开发的论坛非常相似,其中有: 有权查看话题但不能回复或投票的客人 成员有足够的代表,可以编辑/投票其他主题,默认情况下他们可以回复并拥有与访客相同的权限 几乎无所不能的管理员
我正在使用 zend 1.11 框架和doctrine。我正在发送下面的 ajax 请求来填充下拉列表等...但是一旦 session 过期,我将在 Controller 的每个操作中重定向到登录页面
我在我的一个项目中使用 Zend_Auth,但到目前为止还没有弄清楚如何设置 session 的生命周期,或者如何扩展它(假设它应该运行 5 分钟,并且应该在用户使用时重置为做一个 Action ),
我想用 Zend_Auth 和 Zend_Session 来保存用户 session 和登录信息 什么是实现以下项目的最简单和最好的方法: 1-Disallow multiple concurrent
我正在处理我在 Zend 中的第一次用户登录,但我对 Zend_Auth 有点困惑。我阅读的所有关于它的文章都直接在 Controller 中使用它。但对我来说,在我的用户模型中使用它更有意义,这样每
我是一名优秀的程序员,十分优秀!