简体   繁体   English

Symfony2,路由和访问验证器

[英]Symfony2, routes and access validator

Let's imagine we have user and posts. 假设我们有用户和帖子。 Where post link is 帖子链接在哪里

localhost/post/{postID}

How can i check on sf2 level security is user owner of this post (and redirect if not)? 我如何检查sf2级安全性是该帖子的用户所有者(如果不是,请重定向)? I know not much solutions but don't want to use then (I don't want discuss here why). 我知道的解决方案不多,但不想使用它(我不想在这里讨论原因)。

I. Simple check in controller. I.简单检查控制器。 This one looks like simple check (by service or right in action). 这看起来像简单的检查(通过服务或实际操作)。

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

II. II。 Through EventListener. 通过EventListener。 This case better, but not good, because I need to set on each route specific rule. 这种情况更好,但不是很好,因为我需要在每个路由上设置特定规则。 And this listener will be executed every time, even if it will have checker (do check or not) I don't want this one. 而且此侦听器将每次执行一次,即使它具有检查器(是否执行检查),我也不要。

Is there are other solutions for this one. 还有其他解决方案吗?

Also interesting how will it looks like to check 'have user permission to edit\\delete existing post'. 同样有趣的是,如何检查“具有编辑/删除现有帖子的用户权限”。

You can create a PostAuthorizer whose task would be to check whether a user can do something on a post or not. 您可以创建一个PostAuthorizer其任务是检查用户是否可以在帖子上做某事。 For this to work, you can inject a AuthenticatedUserProvider to get the authenticated user straight away in your PostAuthorizer . 为此,您可以注入AuthenticatedUserProvider ,以便直接在PostAuthorizer获取经过身份验证的用户。

1 Create an AuthenticatedUserProvider (I suppose you're using FOSUserBundle like everyone). 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 And declare it as a service: 2并将其声明为服务:

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

3 Create a PostAuthorizer 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 And declare it as a service 4并将其声明为服务

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

5 Finally, in your controller (or in a post provider if you want), you can simply do this: 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