gpt4 book ai didi

php - 在 Zend Framework 之上处理诸如登录页面之类的内容的最佳方式是什么? (为什么我的实现会爆炸?)

转载 作者:可可西里 更新时间:2023-10-31 23:10:50 26 4
gpt4 key购买 nike

编辑: 抱歉这里有大量代码;我不确定到底发生了什么,所以为了安全起见,我包含了更多内容。

我目前有一个登录页面,该页面外包给中央身份验证服务。我想对用户进行权限检查。如果用户未登录,我想将他们重定向到登录页面,并让登录页面重定向他们执行他们最初执行的任何操作,再次运行访问检查。如果他们没有权限,我想将他们重定向到拒绝访问的页面。

这是我到目前为止所做的:

将这一行添加到我的 application.ini:

resources.frontController.actionHelperPaths.Cas_Controller_Action_Helper = APPLICATION_PATH "/controllers/helpers"

创建文件$/application/controllers/helpers/PermissionRequire.php:

<?php
/**
* This class is used in order to require that a user have a given privilege before continuing.
*
* @copyright 2011 Case Western Reserve University, College of Arts and Sciences
* @author Billy O'Neal III (bro4@case.edu)
*/

class Cas_Controller_Action_Helper_PermissionRequire extends Zend_Controller_Action_Helper_Abstract
{
/**
* Cleans up the supplied list of privileges. Strings are turned into the real privilege objects (Based on name),
* privilege objects are left alone.
*
* @static
* @param array|Privilege|string $privileges
* @return array
*/
private static function CleanPrivileges($privileges)
{
if (!is_array($privileges))
{
$privileges =
array
(
$privileges
);
}
$strings = array_filter($privileges, 'is_string');
$objects = array_filter($privileges, function($o)
{
return $o instanceof Privilege;
});
$databaseObjects = PrivilegeQuery::create()->filterByName($strings)->find();
return array_combine($objects, $databaseObjects);
}

/**
* Generic implementation for checking whether a user can visit a page.
* @param Privilege|string|array $privileges Any number of privileges which are required to access the given
* page. If ANY privilege is held by the user, access is allowed.
* @param AccessControlList The acl which is being checked. Defaults to the application.
*/
public function direct($privileges, $acl = null)
{
$privileges = self::CleanPrivileges($privileges);
if ($acl === null)
{
$acl = AccessControlListQuery::getApplication();
}
$redirector = $this->getActionController()->getHelper('redirector');
/** @var Zend_Controller_Action_Helper_Redirector $redirector */
$redirector->setCode(307);
if (Cas_Model_CurrentUser::IsLoggedIn() && (!Cas_Model_CurrentUser::AccessCheck($acl, $privileges)))
{
$redirector->gotoSimple('accessdenied', 'login');
}
else
{
$returnData = new Zend_Session_Namespace('Login');
$returnData->params = $this->getRequest()->getParams();
$redirector->setGotoSimple('login', 'login');
$redirector->redirectAndExit();
}
}
}

这是登录 Controller :

<?php

/**
* LoginController - Controls login access for users
*/

require_once 'CAS.php';

class LoginController extends Zend_Controller_Action
{
/**
* Logs in to the system, and redirects to the calling action.
*
* @return void
*/
public function loginAction()
{
//Authenticate with Login.Case.Edu.
phpCAS::client(CAS_VERSION_2_0, 'login.case.edu', 443, '/cas', false);
phpCAS::setNoCasServerValidation();
phpCAS::forceAuthentication();

$user = CaseIdUser::createFromLdap(phpCAS::getUser());
Cas_Model_CurrentUser::SetCurrentUser($user->getSecurityIdentifier());

$returnData = new Zend_Session_Namespace('Login');
/** @var array $params */
$redirector = $this->_helper->redirector;
/** @var Zend_Controller_Action_Helper_Redirector $redirector */
$redirector->setGotoRoute($returnData->params, 'default', true);
$returnData->unsetAll();
$redirector->redirectAndExit();
}

/**
* Logs the user out of the system, and redirects them to the index page.
*
* @return void
*/
public function logoutAction()
{
Cas_Model_CurrentUser::Logout();
$this->_helper->redirector->gotoRoute('index','index', 'default', true);
}

/**
* Returns an access denied view.
*
* @return void
*/
public function accessdeniedAction()
{
//Just display the view and punt.
}
}

问题是在登录 Controller 中,当它准备将用户重定向到的 URL 时,“params”似乎是 null。此外,当有 POST 数据到调用 $this->_helper->permissionRequire(SOME PRIVILEGE) 的 Controller 时,这将不起作用。

有没有更好的方法来存储请求的整个状态,并生成与该请求完全匹配的重定向?

附言哦,这是一个使用该助手的示例 Controller :

<?php

/**
* Serves as the index page; does nothing but display views.
*/

class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
$renderer = $this->getHelper('ViewRenderer');
/** @var $renderer Zend_Controller_Action_Helper_ViewRenderer */
if (Cas_Model_CurrentUser::IsLoggedIn())
{
$this->_helper->permissionRequire(Cas_Model_Privilege::GetLogin());
$this->render('loggedin');
}
else
{
$this->render('loggedout');
}
}
}

最佳答案

既然您如此热衷于保存请求的 POST 状态,并且因为我自己也一直在研究这个相同的想法很长一段时间,那么像下面这样的东西怎么样。尽管如此,它仍未经过测试,所以我很想听听这样设置保存的请求是否真的按预期工作的结果。 (暂时懒得测试,抱歉)。

在你的配置文件中:

resources.frontController.plugins[] = "Cas_Controller_Plugin_Authenticator"

这是插件:

class Cas_Controller_Plugin_Authenticator
extends Zend_Controller_Plugin_Abstract
{
public function routeStartup( Zend_Controller_Request_Abstract $request )
{
if( Zend_Auth::getInstance()->hasIdentity() )
{
if( null !== $request->getParam( 'from-login', null ) && Zend_Session::namespaceIsset( 'referrer' ) )
{
$referrer = new Zend_Session_Namespace( 'referrer' );
if( isset( $referrer->request ) && $referrer->request instanceof Zend_Controller_Request_Abstract )
{
Zend_Controller_Front::getInstance()->setRequest( $referrer->request );
}
Zend_Session::namespaceUnset( 'referrer' );
}
}
else
{
$referrer = new Zend_Session_Namespace( 'referrer' );
$referrer->request = $this->getRequest();
return $this->_redirector->gotoRoute(
array(
'module' => 'default',
'controller' => 'user',
'action' => 'login'
),
'default',
true
);
}
}
}

插件应该检查​​ routeStartup 用户是否通过了身份验证;

  • 如果用户不是:它将当前请求对象保存在 session 中并重定向到 UserController::loginAction()。 (见下文)
  • 如果用户是:它从 session 中检索保存的请求对象(如果可用,并且如果用户刚刚登录)并替换 frontController 中的当前请求对象(我认为它是路由器的代理)。

总而言之,如果您想要更灵活地确定哪些模块/ Controller /操作参数需要身份验证和授权(我想您想要),您可能希望将一些检查移动到另一个钩子(Hook)而不是 routeStartup :即routeShutdowndispatchLoopStartuppreDispatch。因为到那时应该知道 Action 参数。作为一项额外的安全措施,您可能还需要比较原始请求和替换请求的操作参数(模块/ Controller /操作),以确定您处理的是否是正确保存的请求。

此外,您可能需要在部分或所有 Hook 中对新请求对象设置 $request->setDispatched( false )。虽然不完全确定:请参阅 docs .

这是一个示例登录 Controller :

class UserController
extends Zend_Controller_Action
{
public function loginAction()
{
$request = $this->getRequest();
if( $request->isPost() )
{
if( someAuthenticationProcessIsValid() )
{
if( Zend_Session::namespaceIsset( 'referrer' ) )
{
$referrer = new Zend_Session_Namespace( 'referrer' );
if( isset( $referrer->request ) && $referrer->request instanceof Zend_Controller_Request_Abstract )
{
return $this->_redirector->gotoRoute(
array(
'module' => $referrer->request->getModuleName(),
'controller' => $referrer->request->getControllerName(),
'action' => $referrer->request->getActionName(),
'from-login' => '1'
),
'default',
true
);
}
}

// no referrer found, redirect to default page
return $this->_redirector->gotoRoute(
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index'
),
'default',
true
);
}
}

// GET request or authentication failed, show login form again
}
}

出于安全原因,您可能希望设置一个过期跳数为 1 的 session 变量,而不是“from-login”查询字符串变量。

最后,说了这么多;您可能首先要彻底考虑您是否真的想要这种行为。您当然知道,POST 请求通常会禁止敏感的状态更改操作(创建、删除等)。我不确定用户通常会在登录后(在他们的 session 刚刚过期后)立即期望这种行为。此外,您可能需要考虑可能导致应用程序本身出现意外行为的场景。我现在想不出任何具体细节,但如果我再考虑一下,我相信我可以想出一些。

HTH

编辑
忘记在登录过程后添加正确的重定向操作

关于php - 在 Zend Framework 之上处理诸如登录页面之类的内容的最佳方式是什么? (为什么我的实现会爆炸?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5189450/

26 4 0
文章推荐: html - 大写的 "JPG"扩展与小写的 "jpg"不同?
文章推荐: php - magento 将自定义输入字段添加到管理员中的客户帐户表单
文章推荐: css - 有没有办法使用
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com