- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
编辑: 抱歉这里有大量代码;我不确定到底发生了什么,所以为了安全起见,我包含了更多内容。
我目前有一个登录页面,该页面外包给中央身份验证服务。我想对用户进行权限检查。如果用户未登录,我想将他们重定向到登录页面,并让登录页面重定向他们执行他们最初执行的任何操作,再次运行访问检查。如果他们没有权限,我想将他们重定向到拒绝访问的页面。
这是我到目前为止所做的:
将这一行添加到我的 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
用户是否通过了身份验证;
UserController::loginAction()
。 (见下文)总而言之,如果您想要更灵活地确定哪些模块/ Controller /操作参数需要身份验证和授权(我想您想要),您可能希望将一些检查移动到另一个钩子(Hook)而不是 routeStartup
:即routeShutdown
、dispatchLoopStartup
或preDispatch
。因为到那时应该知道 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/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!