权限和凭据[[AND OR]]不使用检查数据库而不是会话凭据的代码段

时间:2012-03-20 13:06:41

标签: php symfony1 symfony-1.4

我发现这个很棒的代码片段在用户会话期间更改用户凭据的情况下运行得非常好。 hasCredential()方法默认查看数据库而不是用户的会话 - 这完全满足我的需求(因为用户的凭据通常在用户会话期间以编程方式更改)。所以我真的需要保持这个功能。

但是,对于具有多个凭证的情况,OR情况:[[A,B]]或AND情况:[A,B]代码片段失败,因为它只检查一个实例并且不读取AND OR实例的yaml安全文件。

我正在寻找有关如何调整代码段以考虑AND OR yaml凭据权限的帮助。这是代码片段:

public function hasCredential($permission_name)
{
//this overrides the default action (hasCredential) and instead of checking
//the user's session, it now checks the database directly.  
if (!$this->isAuthenticated()) {
  return false;
}
$gu = $this->getGuardUser();
$groups = $gu->getGroups();
$permissions = $gu->getPermissions();

$permission_names = array();
foreach($permissions as $permission) {
  $permission_names[] = $permission->getName();
}
foreach($groups as $group) {
  $group_permissions = $group->getPermissions();
  foreach($group_permissions as $group_permission) {
    $permission_names = array_merge($permission_names, array($group_permission->getName()));
  }
}
$permission_names = array_unique($permission_names);
return (in_array($permission_name, $permission_names)) ? true : false;
}

编辑:

我想我需要将上面的代码与下面的原始hasCredential()合并,但我正在努力解决这个问题:

public function hasCredential($credentials, $useAnd = true)
{
if (null === $this->credentials)
{
  return false;
}

if (!is_array($credentials))
{
  return in_array($credentials, $this->credentials);
}

// now we assume that $credentials is an array
$test = false;

foreach ($credentials as $credential)
{
  // recursively check the credential with a switched AND/OR mode
  $test = $this->hasCredential($credential, $useAnd ? false : true);

  if ($useAnd)
  {
    $test = $test ? false : true;
  }

  if ($test) // either passed one in OR mode or failed one in AND mode
  {
    break; // the matter is settled
  }
}

if ($useAnd) // in AND mode we succeed if $test is false
{
  $test = $test ? false : true;
}

return $test;
}

1 个答案:

答案 0 :(得分:0)

我认为我找到了正确的hasCredential方法实现,该方法覆盖了sfGuardSecurityUser类中的原始代码。代码要求基础GuardUser模型从数据库重新加载所有权限和组,并在检查凭据之前将这些凭据添加到SecurityUser对象。

/**
 * Returns whether or not the user has the given credential.
 * 
 * EXTENDED to reload all permission so that changes take
 * immediate effect and user does not have to log out
 *
 * @param string $credential The credential name
 * @param boolean $useAnd Whether or not to use an AND condition
 * @return boolean
 */
public function hasCredential($credential, $useAnd = true)
{
  if (empty($credentials))
  {
    return true;
  }

  if (!$this->getGuardUser())
  {
    return false;
  }

  if ($this->getGuardUser()->getIsSuperAdmin())
  {
    return true;
  }

  if (!$this->isAuthenticated()) {
    return false;
  }

  $gu = $this->getGuardUser();
  $groups = $gu->getGroups();
  $permissions = $gu->getPermissions();

  $permission_names = array();
  foreach($permissions as $permission) {
    $permission_names[] = $permission->getName();
  }
  foreach($groups as $group) {
    $group_permissions = $group->getPermissions();
    foreach($group_permissions as $group_permission) {
      $permission_names = array_merge($permission_names, array($group_permission->getName()));
    }
  }
  $permission_names = array_unique($permission_names);

  if (!is_array($credentials))
  {
    return in_array($credentials, $permission_names);
  }

  // now we assume that $credentials is an array
  $test = false;

  foreach ($credentials as $credential)
  {
    // recursively check the credential with a switched AND/OR mode
    $test = $this->hasCredential($credential, $useAnd ? false : true);

    if ($useAnd)
    {
      $test = $test ? false : true;
    }

    if ($test) // either passed one in OR mode or failed one in AND mode
    {
      break; // the matter is settled
    }
  }

  if ($useAnd) // in AND mode we succeed if $test is false
  {
    $test = $test ? false : true;
  }

  return $test;
}