我正致力於開發基於PHP的訪問控制庫,名爲PHP-Bouncer。 PHP-Bouncer允許用戶定義角色列表,每個角色可以訪問哪些頁面,並且每個角色也可以定義覆蓋其他頁面的頁面列表(因此,進入覆蓋頁面會將您重定向到覆蓋頁面) 。這裏是如何做到這一點的工作(從Access Managed Example文檔中)的一個例子:防止訪問控制庫中的無限重定向
$bouncer = new Bouncer();
// Add a role Name, Array of pages role provides
$bouncer->addRole("Public", array("index.php", "about.php", "fail.php"));
// Add a role Name, Array of pages role provides
$bouncer->addRole("Registered User", array("myaccount.php", "editaccount.php", "viewusers.php"));
// Add a role Name, Array of pages role provides List of pages that are overridden by other pages
$bouncer->addRole("Admin", array("stats.php", "manageusers.php"), array("viewusers.php" => "manageusers.php"));
// Here we add some users. The user class here extends the BouncerUser class, so it can still do whatever you
// would normally create a user class to do..
$publicUser = new User();
$registeredUser = new User();
$adminUser = new User();
$registeredAndAdmin = new User();
$publicUser->addRole("Public");
$registeredUser->addRole("Public"); // We add the public group to all users since they need it to see index.php
$registeredUser->addRole("Registered User");
$adminUser->addRole("Public"); // We add the public group to all users since they need it to see index.php
$adminUser->addRole("Admin");
$registeredAndAdmin->addRole("Public"); // We add the public group to all users since they need it to see index.php
$registeredAndAdmin->addRole("Registered User");
$registeredAndAdmin->addRole("Admin");
$bouncer->manageAccess($publicUser->getRoles(), substr($_SERVER["PHP_SELF"], 1), "fail.php");
這裏就是我遇到的問題:在你上面看到的manageAccess功能,一切正常,只要角色定義並且所有用戶都可以訪問fail.php(或者fail.php沒有實現$ bouncer對象)。只要有人創建了一個具有固有衝突的角色(例如自己覆蓋頁面)或未能讓所有用戶訪問失敗頁面,manageAccess函數就會導致無限循環。由於這是不好的,我想解決它。然而,我不確定什麼是允許一些重定向的最佳方法(可能是重定向兩到三次可能是理想的行爲),同時防止無限循環。這裏是manageAccess功能:
/**
* @param array $roleList
* @param string $url
* @param string $failPage
*/
public function manageAccess($roleList, $url, $failPage = "index.php"){
$granted = false;
foreach($roleList as $role){
if(array_key_exists($role, $this->roles)){
$obj = $this->roles[$role];
/** @var $obj BouncerRole */
$response = $obj->verifyAccess($url);
if($response->getIsOverridden()){ // If access to the page is overridden forward the user to the overriding page
$loc = ($obj->getOverridingPage($url) !== false) ? $obj->getOverridingPage($url) : $failPage;
$locationString = "Location: ".$loc;
header($locationString);
// I broke something in the last commit, perhaps this comment will help?
}
if($response->getIsAccessible()){ // If this particular role contains access to the page set granted to true
$granted = true; // We don't return yet in case another role overrides.
}
}
}
// If we are here, we know that the page has not been overridden
// so let's check to see if access has been granted by any of our roles.
// If not, the user doesn't have access so we'll forward them on to the failure page.
if(!$granted){
$locationString = "Location: ".$failPage."?url=".urlencode($url)."&roles=".urlencode(serialize($roleList));
header($locationString);
}
}
有什麼建議嗎?
你應該在第一個'header($ locationString)'之後加上'return'。 – Florent 2012-07-27 15:27:15
即使執行? – 2012-07-27 15:37:05
如果您沒有返回,則可能會發送多個「位置」標題。 – Florent 2012-07-27 15:40:38