让我们想象一下,我们有用户和帖子。帖子链接在哪里
localhost/post/{postID}
如何检查sf2级别的安全性是此帖子的用户所有者(如果没有,则重定向)?我知道解决方案不多,但不想使用(我不想在此讨论原因)。
予。简单检查控制器。这个看似简单的检查(通过服务或正确的行动)。
if ($this->isOwner()){
return $this->redirect(...);
}
II。通过EventListener。这种情况更好,但并不好,因为我需要设置每个路由特定的规则。这个监听器每次都会执行,即使它有检查器(做或不检查)我不想要这个。
这个还有其他解决方案吗?
同样有趣的是如何检查'拥有编辑\删除现有帖子的用户权限'。
答案 0 :(得分:1)
您可以创建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