繁体   English   中英

Symfony2,路由和访问验证器

[英]Symfony2, routes and access validator

假设我们有用户和帖子。 帖子链接在哪里

localhost/post/{postID}

我如何检查sf2级安全性是该帖子的用户所有者(如果不是,请重定向)? 我知道的解决方案不多,但不想使用它(我不想在这里讨论原因)。

I.简单检查控制器。 这看起来像简单的检查(通过服务或实际操作)。

if ($this->isOwner()){
return $this->redirect(...);
}

II。 通过EventListener。 这种情况更好,但不是很好,因为我需要在每个路由上设置特定规则。 而且此侦听器将每次执行一次,即使它具有检查器(是否执行检查),我也不要。

还有其他解决方案吗?

同样有趣的是,如何检查“具有编辑/删除现有帖子的用户权限”。

您可以创建一个PostAuthorizer其任务是检查用户是否可以在帖子上做某事。 为此,您可以注入AuthenticatedUserProvider ,以便直接在PostAuthorizer获取经过身份验证的用户。

1创建一个AuthenticatedUserProvider (我想您像所有人一样都在使用FOSUserBundle)。

<?php

namespace Acme\PostBundle\Security;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\UserBundle\Model\UserInterface;

/**
 * Provides the authenticated user
 */
class AuthenticatedUserProvider
{
    /**
     * The security context
     *
     * @var SecurityContextInterface
     */
    protected $securityContext;

    public function __construct(SecurityContextInterface $securityContext)
    {
        $this->securityContext = $securityContext;
    }

    /**
     * Gets the current authenticated user
     *
     * @return UserInterface
     */
    public function getAuthenticatedUser()
    {
        $user = $this->securityContext->getToken()->getUser();

        if (!$user instanceof UserInterface) {
            throw new AccessDeniedException('Must be logged in with a UserInterface instance');
        }

        return $user;
    }
}

2并将其声明为服务:

services:
    #Authenticated User Provider
    acme_post.autenticated_user.provider:
        class: Acme\PostBundle\Security\AuthenticatedUserProvider
        arguments:
            securityContext: "@security.context"

3创建一个PostAuthorizer

<?php

namespace Acme\PostBundle\Security;

use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Acme\PostBundle\Entity\PostInterface;
use Acme\PostBundle\Security\AuthenticatedUserProvider;

/**
 * Manages permissions to manipulate posts
 */
class PostAuthorizer
{
    /**
     * The user provider
     *
     * @var AuthenticatedUserProvider
     */
    protected $authenticatedUserProvider;

    public function __construct(AuthenticatedUserProvider $authenticatedUserProvider)
    {
        $this->authenticatedUserProvider = $authenticatedUserProvider;
    }

    /**
     * Tells if the current user is allowed
     * to see this post
     *
     * @param PostInterface $post
     * @return boolean
     */
    public function canSeePost(PostInterface $post)
    {
        return ($this->getAuthenticatedUser()->getId()  === $post->getOwner()->getId());
    }

    /**
     * Tells if the current participant is allowed
     * to delete this post
     *
     * @param PostInterface $post
     * @return boolean
     */
    public function canDeletePost(PostInterface $post)
    {
        return $this->canSeePost($post);
    }

    /**
     * Tells if the current participant is allowed
     * to edit this post
     *
     * @param PostInterface $post
     * @return boolean
     */
    public function canEditPost(PostInterface $post)
    {
       return $this->canSeePost($post);
    }

    /**
     * Gets the current authenticated user
     *
     * @return FOS\UserBundle\Model\UserInterface
     */

    protected function getAuthenticatedUser()
    {
        return $this->authenticatedUserProvider->getAuthenticatedUser();
    }
}

4并将其声明为服务

services:
    acme_post.post.authorizer:
        class: Acme\PostBundle\Security\PostAuthorizer
        arguments:
            authenticatedUserProvider: "@acme_post.autenticated_user.provider"

5最后,在您的控制器中(或者如果需要,在帖子提供者中),您只需执行以下操作:

if( !$this->container->get('acme_post.post.authorizer')->canSeePost($post) ) {
    throw new AccessDeniedException('You are not allowed to see this post');
}

// can safely display the post now

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM