Zend_Auth最佳实践

时间:2011-04-01 12:46:12

标签: php zend-framework authentication zend-framework-mvc

我的目标是要求登录某些网页。我正在使用Zend Framework MVC,我正在尝试找到有关最佳实践的示例。

关于我正在寻找的一些注意事项:

  • 我希望未登录的用户获得登录框,然后返回登录版本的页面,经过身份验证
  • 我想使用依赖注入,并避免单身人士
  • 小代码占用 - 与Zend mvc结构相关联
  • 登录框应该是一个单独的控制器并执行标题重定向吗?如何在auth成功后返回登录页面?简单地调用登录控制器操作以在登录页面中显示登录框的想法,或者这是否是关于搜索引擎索引的缺点?
  • 能够使用外部库处理cookie

或者完全不同的东西。我是Zend框架的新手,我想以“正确的方式”做到这一点。

3 个答案:

答案 0 :(得分:4)

  
      
  • 我希望未登录的用户获得登录框,然后返回登录状态   在页面的版本中,一次   认证
  •   

使用FrontController plugin并将其重定向或转发至您的loginAction。

  
      
  • 我想使用依赖注入,并避免单身人士
  •   

Zend Framework,目前没有发布任何DI系统,但Zend_Application_Resource_ *实际上取代了它。你需要什么样的依赖?

  
      
  • 小代码占用 - 与Zend mvc结构相关联
  •   

这取决于你。

  
      
  • 登录框应该是一个单独的控制器并执行标题重定向吗?怎么样   在auth之后返回登录页面   成功?简单地称之为的想法   登录控制器动作来显示   登录页面中的登录框,或者是   这是一个关于搜索的缺点   引擎索引?
  •   

我主要使用特殊AuthControllerLoginAction& LogoutAction。要将用户重定向到正在查看的页面,我总是在我的表单中添加returnUrl元素,并且我注入所请求的URL的值以便能够重定向用户,如果没有,我重定向他到索引/仪表板,取决于。

  
      
  • 能够使用外部库处理cookie
  •   

Zend_Auth允许您设置own storage mechanism,所以只需实现界面。

$auth = Zend_Auth::getInstance();
$auth->setStorage(new My_Auth_Storage());

但是 从不将身份验证结果存储在Cookie中,它很容易修改并访问您的网站。

您还可以查看我的previous answer之一。

答案 1 :(得分:4)

您可以使用Zend_AuthZend_Acl的组合。为了扩展其他答案,我举一个简短的例子,说明如何使用zend框架管理身份验证:

首先,您需要设置一个插件,以预捕发所有请求,并检查是否允许客户端访问某些数据。这个插件可能看起来像这样:

class Plugin_AccessCheck extends Zend_Controller_Plugin_Abstract {

    private $_acl = null;

    public function __construct(Zend_Acl $acl) {
        $this->_acl = $acl;
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        //get request information
        $module = $request->getModuleName ();
        $resource = $request->getControllerName ();
        $action = $request->getActionName ();

        try {
            if(!$this->_acl->isAllowed(Zend_Registry::get('role'), 
                                $module . ':' . $resource, $action)){
                $request->setControllerName ('authentication')
                        ->setActionName ('login');
            }
        }catch(Zend_Acl_Exception $e) {
            $request->setControllerName('index')->setActionName ('uups');
        }
    }
}

因此,每个用户类型都具有您在acl库中定义的特定权限。在每个请求中,您都会检查是否允许用户访问资源。如果没有,您将重定向到登录页面,否则preDispatch会将用户传递给资源。

Zend_Acl中,您可以定义允许或拒绝访问的角色,资源和权限,例如:

class Model_LibraryAcl extends Zend_Acl {
    public function __construct() {

        $this->addRole(new Zend_Acl_Role('guests'));
        $this->addRole(new Zend_Acl_Role('users'), 'guests');
        $this->addRole(new Zend_Acl_Role('admins'), 'users');                

        $this->add(new Zend_Acl_Resource('default'))
             ->add(new Zend_Acl_Resource('default:authentication'), 'default')
             ->add(new Zend_Acl_Resource('default:index'), 'default')
             ->add(new Zend_Acl_Resource('default:error'), 'default');

        $this->allow('guests', 'default:authentication', array('login'));
        $this->allow('guests', 'default:error', 'error');

        $this->allow('users', 'default:authentication', 'logout');          
    }
}

然后你必须在你的bootstrap文件中设置acl和auth:

    private $_acl = null;

    protected function _initAutoload() {

       //...your code           
       if (Zend_Auth::getInstance()->hasIdentity()){
        Zend_Registry::set ('role',
                     Zend_Auth::getInstance()->getStorage()
                                              ->read()
                                              ->role);
        }else{
            Zend_Registry::set('role', 'guests');
        }

        $this->_acl = new Model_LibraryAcl ();
        $fc = Zend_Controller_Front::getInstance ();
        $fc->registerPlugin ( new Plugin_AccessCheck ( $this->_acl ) );

        return $modelLoader;
    }

最后在您的身份验证控制器中,您必须使用自定义身份验证适配器并设置登录和注销操作:

public function logoutAction() {
    Zend_Auth::getInstance ()->clearIdentity ();
    $this->_redirect ( 'index/index' );
}

private function getAuthAdapter() {
    $authAdapter = new Zend_Auth_Adapter_DbTable ( 
                        Zend_Db_Table::getDefaultAdapter ());
    $authAdapter->setTableName('users')
                ->setIdentityColumn('email')
                ->setCredentialColumn ('password')
                ->setCredentialTreatment ('SHA1(CONCAT(?,salt))');

    return $authAdapter;
}

在登录操作中,您需要将登录数据传递给执行身份验证的身份验证适配器。

$authAdapter = $this->getAuthAdapter ();
$authAdapter->setIdentity ( $username )->setCredential ( $password );
$auth = Zend_Auth::getInstance ();
$result = $auth->authenticate ( $authAdapter );

if ($result->isValid ()) {
    $identity = $authAdapter->getResultRowObject ();
    if ($identity->approved == 'true') {
        $authStorage = $auth->getStorage ();
        $authStorage->write ( $identity );
        $this->_redirect ( 'index/index' );
    } else {
       $this->_redirect ( 'authentication/login' );
  }

就是这样。我建议你在zend auth和zend acl。

上的youtube上使用HOW TO

答案 2 :(得分:1)

不确定这是否是最佳做法,但如果我要实现您的目标,那么我将执行以下操作:

  1. 使用唯一可识别的提交按钮创建LoginForm(稍后解释)
  2. 使用方法AuthServicegetLoginFormlogin以及以下一项或全部创建logoutgetIdentityhasIdentity和类似方法
  3. 创建一个包含此服务实例的viewhelper,并根据hasIdentity的结果,在需要此功能的视图中呈现LoginForm或呈现登录用户的身份。
  4. 创建一个前控制器插件,该插件还具有该服务的实例并实现preDispatch插件挂钩。给它一些配置来探测哪些动作。如果AuthService->hasIdentity()返回true,则不执行任何操作。如果请求是发布请求,则查找唯一可识别的提交按钮名称,即:$request->getPost( 'loginSubmitButton', null );默认为null(如果不可用)。如果不是null在服务上执行login( $request->getPost() )。如果成功,则重定向到相同的操作,如果不成功,则再次在viewhelper中呈现表单(自动显示错误)。
  5. 该服务可以由viewhelper和前端控制器插件获取,一些服务定位器通过在引导程序中将服务注册到ServiceAbstract::getService( 'Auth' )来执行ServiceAbstract之类的操作。