【问题标题】:Symfony Voter : Access denied, the user is neither anonymous, nor remember-meSymfony Voter:访问被拒绝,用户既不是匿名的,也不是记住我
【发布时间】:2016-07-28 08:05:11
【问题描述】:

我对 Symfony 还是很陌生。我正在尝试在管理区域使用选民。

我希望管理员 (ROLE_ADMIN) 只有在他是超级管理员 (ROLE_SUPER_ADMIN) 时才能删除(移除)用户。

我的防火墙似乎工作正常,因为我可以登录管理区域并做我想做的事,直到我不使用投票者。这是我当前用户对象的转储:

User {#300 ▼
  -id: 1
  -password: "$2y$13$e3LL2N/pYGrGn.7EFikqSuAMSkLolcnggtf1HsBgNMzdXnal1AIua"
  -username: "JustMe"
  -email: "me@me.fr"
  -isActive: true
  -roles: array:1 [▼
    0 => "ROLE_ADMIN"
  ]
}

一旦我在控制器中使用了denyUnlessGranted(),我就会得到这个异常:

DEBUG - Access denied, the user is neither anonymous, nor remember-me.
ERROR - Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: "Access Denied." at /Volumes/Work/MAMP htdocs/a-symfony-re/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php line 119 

这是我的安全配置:

role_hierarchy:
    ROLE_AUTHOR: ROLE_USER
    ROLE_EDITOR: ROLE_AUTHOR
    ROLE_ADMIN : [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]

firewalls:
    # disables authentication for assets and the profiler, adapt it according to your needs
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    main:
        anonymous: ~
        pattern: ^/
        provider: app_users_provider
        form_login:
            login_path: jst_login
            check_path: jst_login_check
        logout:
            path: jst_logout
            target: /

access_decision_manager:
    strategy: unanimous

这是我的控制器中的一个基本操作,在不使用投票器之前可以正常工作:

public function deleteUserAction(User $user)
{
    $this->denyAccessUnlessGranted('delete', $user);
    $currentUser = $this->getUser();
    $role = $currentUser->getRoles[0];

    return new Response('Delete User AppBundle:AdminController:deleteUser : '.$role);
}

这是非常简单的选民:

namespace AppBundle\Security;

use AppBundle\Entity\User;
use AppBundle\Entity\Role;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;

class UserVoter extends Voter
{
    const EDIT = 'edit';
    const DELETE = 'delete';
    const CREATE = 'create';

    private $decisionManager;

    public function __construct(AccessDecisionManagerInterface, $decisionManager)
    {
        $this->decisionManager = $decisionManager;
    }

    public function support($attribute, $subject)
    {
        if (!in_array($attribute, array(selt::DELETE))) {
            return false;
        }
        if (!$subject instanceOf USER) {
            return false;
        }

        return true;
    }

    public function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        $currentUser = $token->getUser();
        $user = $subject;

        if (!$currentUser instanceOf User) {
            return false;
        }

        switch ($attribute) {
            case self::DELETE :
                //return $this->canDelete( $token );
                return $this->canDelete($user, $currentUser);
                break;
            default:
                throw new \LogicException('this code shoudn\'t be executed');
        }
    }

    private function canDelete($user, $currentUser)
    {
        //return $this->decisionManager->decide( $token, array( 'ROLE_ADMIN' ) );
        return $currentUser->getRoles()[0] == 'SUPER_ADMIN';
    }
}

如您所见,我已经尝试使用 AccessDecisionManagerInterface 没有结果..

Et bien heuuu .. 有什么帮助吗? ;-)

谢谢!

【问题讨论】:

  • 你的support 函数中有错字:selt::DELETE 应该是self::DELETE ?
  • 你说得对!但仍然有这个异常..

标签: php symfony security


【解决方案1】:

ROLE_SUPER_ADMIN 在你的 role_hierarchy 中在哪里?

在你的 voteOnAttribute 函数中试试这个。

  case self::DELETE:
            // if the user is an super admin, allow them to create new posts
            if ($this->decisionManager->decide($token,  array('ROLE_SUPER_ADMIN'))) {
                return true;
            }

当您登录网站时,您的角色是什么?检查分析器

【讨论】:

  • 我已经省略了角色,是的,但仍然有这个问题。还尝试简单地尝试匹配 ROLE_AMDIN 但仍然抛出异常。我在 ADMIN_ROLE 下登录
【解决方案2】:

您的安全配置中没有角色 ROLE_SUPER_ADMIN。 将其添加到您的角色层次结构中:

role_hierarchy:
    ROLE_AUTHOR: ROLE_USER
    ROLE_EDITOR: ROLE_AUTHOR
    ROLE_ADMIN : [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
    ROLE_SUPER_ADMIN: ROLE_ADMIN
...

评论后更新

//return $this->decisionManager->decide( $token, array( 'ROLE_ADMIN' ) ); 的问题是,您的逻辑在哪里定义用户是否可以删除另一个用户? 决策管理器不知道您是否不实现接口并使用该实例。

对于return $currentUser->getRoles()[0] == 'ROLE_ADMIN';好吧,可能令牌存储返回的用户有几个角色,ROLE_ADMIN不是第一个。在这种情况下尝试使用:

return in_array("ROLE_SUPER_ADMIN", $tokenInterface->getUser()->getRoles();

【讨论】:

  • 是的,我忘记了 ROLE_SUPER_ADMIN 角色 un security.yml 但仍然抛出相同的错误。无论如何,我还尝试简化尝试与 ROLE_ADMIN 匹配的 Voter,但仍会引发异常。我在我的 Voter 中尝试了 2 种方法: return $this->decisionManager->decide( $token, array( 'ROLE_ADMIN' ) );并返回 $currentUser->getRoles()[0] == 'ROLE_ADMIN';两种方法都失败了。
  • 好的,我终于在我的代码中发现了一些错误。非常感谢您的建议。但似乎注意到了 1 点:在选民自定义类中,我们可以使用 AccessDecisionManager,因为它通过检查令牌用户角色来保存逻辑。所以 $this->decisionManager->decide( $token, array( "ROLE_ADMIN" ) );效果很好。这是我的错别字和错误:1:构造函数参数类型后昏迷,2:不支持的方法“支持”(“支持”是好的方法),最重要的是,我错过了在 app/config/services.yml 中配置我的服务。
【解决方案3】:

这个错误也可能是由 symfony 3.0 和 1.6.0 版本中的jms/security-extra-bundle 不兼容引起的。

如果您使用 jms-security-extra-bundle,请尝试在 1.6.1 或更高版本中使用它!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多