dmytrof/ access-permissions-bundle
Symfony AccessPermissionsBundle
1.2.1
2021-06-18 11:47 UTC
Requires
- php: ^7.2 || ^8.0
- doctrine/inflector: ^2.0
- doctrine/orm: ^2.6
- symfony/form: ^4.3 || ^5.0
- symfony/framework-bundle: ^4.3 || ^5.0
- symfony/security-bundle: ^4.3 || ^5.0
- symfony/translation: ^4.3 || ^5.0
- symfony/validator: ^4.3 || ^5.0
Requires (Dev)
- phpunit/phpunit: ^8.3 || ^9.1
Suggests
- symfony/security: Adds access permissions for administrator for entities and other resources
README
此包可以帮助您为您的Symfony 4/5应用程序创建访问权限
安装
步骤1:安装包
$ composer require dmytrof/access-permissions-bundle
步骤2:启用包
<?php
// config/bundles.php
return [
// ...
Dmytrof\AccessPermissionsBundle\DmytrofAccessPermissionsBundle::class => ['all' => true],
];
用法
阅读symfony/security的官方文档,并将安全组件安装到您的项目中。
1. 为Article实体创建投票者
// src/Security/ArticleVoter.php
use App\Model\{Article, Author};
use Dmytrof\AccessPermissionsBundle\Security\{AbstractVoter, CRUDVoterInterface, Traits\CRUDVoterTrait};
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class ArticleVoter extends AbstractVoter implements CRUDVoterInterface
{
use CRUDVoterTrait;
// Put needed resources to subject (Article, Category etc.)
protected const SUBJECT = [
Article::class,
];
public const PREFIX = 'app.article.';
public const VIEW = self::PREFIX.'view';
public const CREATE = self::PREFIX.'create';
public const EDIT = self::PREFIX.'edit';
public const DELETE = self::PREFIX.'delete';
public const ATTRIBUTES = [
self::VIEW,
self::CREATE,
self::EDIT,
self::DELETE,
];
}
2. 将AdminInterface添加到您的User模型中
// src/Entity/User.php
use Symfony\Component\Security\Core\User\UserInterface;
use Dmytrof\AccessPermissionsBundle\Security\AdminInterface;
class User implements UserInterface, AdminInterface
{
//.....
/**
* Returns admin access atributes
*/
public function getAdminAccessAttributes(): array
{
// Return saved attributes from DB
return [
ArticleVoter::getViewAttribute(),
ArticleVoter::getCreateAttribute(),
ArticleVoter::getEditAttribute(),
];
}
/**
* Returns roles
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
if ($this->isAdmin()) {
$roles[] = 'ROLE_ADMIN';
}
return array_unique($roles);
}
//....
}
3. 在控制器中添加访问检查
//src/Controller/ArticleController.php
/**
* @Route("/api/articles")
*/
class ArticleController extends AbstractController
{
/**
* @Route("/", methods={"GET"})
*/
public function getAll(Request $request)
{
$this->denyAccessUnlessGranted(ArticleVoter::getViewAttribute());
// Fetch article from DB and return response
}
}
此时,AccessDecisionManager "询问" ArticleVoter是否可以RoleAdmin来查看
// Dmytrof\AccessPermissionsBundle\Security\AbstractVoter.php;
/**
* Checks if admin has access to attribute
*/
protected function canRoleAdmin(string $attribute, TokenInterface $token, $subject = null): bool
{
$admin = $token->getUser();
if (!$admin instanceof AdminInterface) {
return true;
}
return in_array($attribute, $admin->getAdminAccessAttributes());
}
您可以为在security.yaml中定义的任何角色或添加到RolesContainer中的角色编写"can-method"。
security:
role_hierarchy:
ROLE_AUTHOR
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
重要提示
/** @var \Dmytrof\AccessPermissionsBundle\Service\RolesContainer $rolesContainer */
$rolesContainer->addRole('ROLE_ANY');
投票者首先尝试调用canRoleAuthorEdit(其中RoleAuthor - 分类的角色ROLE_AUTHOR,Edit - ArticleVoter::EDIT的简写属性)
// src/Security/ArticleVoter.php
/**
* Checks if ROLE_AUTHOR can EDIT the article
*/
protected function canRoleAuthorEdit(TokenInterface $token, $subject = null): bool
{
return $subject instanceof Article // Subject is Article
&& $token->getUser() instanceof Author // Authinticated user is Author
&& $subject->getAuthor() === $token->getUser(); // Authenticated Author is author of the Article
}
/**
* Checks if ROLE_AUTHOR can VIEW, CREATE, DELETE the article
*/
protected function canRoleAuthor(string $attribute, TokenInterface $token, $subject = null): bool
{
switch($attribute) {
case static::VIEW:
case static::CREATE:
return true;
default:
return false;
}
}
记住
- 投票者尝试调用canRoleAuthorEdit。
- 如果方法不存在,将调用canRoleAuthor。
- 如果方法不存在,将调用can。
4. 添加属性标签和描述
在翻译文件夹中创建access_attributes.en.yaml
// translations/access_attributes.en.yaml
app:
label: My application
attributes:
create:
label: Create
view:
label: View
edit:
label: Edit
delete:
label: Delete
subjects:
article:
label: Articles
attributes:
view:
label: View articles
description: Access to view article(s)
create:
label: Create new articles
# edit - default label app.attributes.edit.label will be used
# delete - default label app.attributes.delete.label will be used
author:
label: Authors
# attributes - default app.attributes will be used
5. 管理用户属性
使用表单类型AccessAttributesChoiceType或AccessAttributesCollectionType在您的用户表单类型中管理用户的访问属性。
要在您的API中获取所有访问属性及其描述,请向UserController添加操作。
// src/Controller/UserController.php
public function getAccessAttributes(VotersContainer $votersContainer)
{
return [
'attributes' => $votersContainer->getAttributeDescriptionsCollection()->sort()->getAsArray()
];
}