zycon42 / security
Nette框架的安全扩展
Requires
- php: >= 5.4
- nette/application: ~2.2
- nette/security: ~2.2
- symfony/expression-language: ~2.5
Requires (Dev)
- php: >= 5.5
- jakub-onderka/php-parallel-lint: ~0.7
- mockery/mockery: @stable
- phpunit/phpunit: 4.1.*
This package is not auto-updated.
Last update: 2024-09-24 03:09:40 UTC
README
概览
由于我对当前的Nette授权机制不满意,我决定将Symfony/Security
移植到Nette。
它主要基于Symfony/Security-Core
。遗憾的是,Nette认证机制和Nette\Security\User
类与纯Symfony/Security-Core
不兼容,因此必须重新编写。
目前该项目仅处理授权,您必须使用Nette类。此外,目前不支持ACL。
有关其内部工作原理的更多信息,请参阅symfony安全文档。
要求
此项目需要php 5.4
安装
安装Zycon42/Security的最佳方式是使用Composer
$ composer require zycon42/security:~0.1
然后您必须在config.neon中启用它
extensions: security: Zycon42\Security\DI\SecurityExtension
基本用法
授权的主要入口点是SecurityContext
类。示例用法
if (!$securityContext->isGranted('ROLE_ADMIN')) throw new ForbiddenRequestException('You need to be admin');
上述代码将在当前用户没有名为ADMIN
的角色时拒绝访问。您可以使用IS_AUTHENTICATED
或IS_ANONYMOUS
代替角色,分别仅授予认证用户或匿名用户访问权限。
您还可以利用isGranted
方法的可选二级参数object
,并询问当前用户是否可以在给定的资源上执行给定的操作,如下所示
if (!$securityContext->isGranted('EDIT', $post)) throw new ForbiddenRequestException("You are not able to edit this $post");
投票者
Symfony安全使用投票者的概念,投票者决定用户是否被授予或拒绝。访问决策管理器收集这些投票,并根据它们做出决定。项目包含三个投票者。一个用于角色,第二个用于IS_AUTHENTICATED, IS_ANONYMOUS
令牌,最后一个用于我们将稍后讨论的表达式。
使用投票者,您可以轻松扩展支持的属性和对象的范围。例如,您可以实现一个典型的用例,即用户只能编辑自己的帖子。
创建一个新的投票者,实现Zycon42\Security\Authorization\Voters\IVoter
接口,然后将其在DIC中注册为特定标记
services: foo: class: YourVoter tags: [security.voter]
当您使用security.voter
标记服务时,它将被添加到AccessDecisionManager
中作为投票者。
有关投票者及其实现方法的信息,请参阅symfony文档,仅记住我们使用的是来自nette的IIdentity
而不是TokenInterface
。
表达式
为了能够编写更复杂的访问规则,您可以使用表达式。我们使用symfony/expression-language
来解析它们。
您可以在其中使用以下函数
isAnonymous()
如果当前用户未认证则返回trueisAuthenticated()
如果当前用户已认证则返回truehasRole(string $role)
检查用户是否在给定角色中hasPermission($object, $action)
检查用户是否有权限在对象上执行操作
您还可以访问一些变量
identity
当前用户身份user
nette用户对象Nette\Security\User
object
作为isGranted
方法的第二个参数传递的对象。roles
身份角色的数组
示例用法
$securityContext->isGranted(new Expression("isAuthenticated() && !hasRole('CLIENT')"));
演示者注释
为了能够使用演示者注解来授权/拒绝访问,请在您的受保护演示者中使用此功能,所有需要使用此功能的演示者都应从中派生。
class SecuredPresenter extends BasePresenter { // ... some code /** * @var PresenterRequirementsChecker * @inject */ public $requirementsChecker; /** * {@inheritdoc} */ public function checkRequirements($element) { if (!$this->requirementsChecker->checkRequirement($element, $this->request)) { // logged users get 403 and anonymous users get redirect to sign in if ($this->user->isLoggedIn()) { $expr = $this->requirementsChecker->getFailedExpression(); throw new ForbiddenRequestException("Request didn't passed security expression \"$expr\""); } else { $this->redirect('Sign:in', ['backLink' => $this->storeRequest()]); } } } // ... some code }
请记住,不要在派生演示者中覆盖 checkRequirements
方法。
现在您可以使用 @Security
注解注解演示者和其 action/render/handle
方法。小例子:
/** * @Security("hasRole('ADMIN')") */ class UsersPresenter extends SecuredPresenter { // ... some code }
或者注解 action
方法
class UsersPresenter extends SecuredPresenter { // ... some code /** * @Security("hasRole('ADMIN')") */ public function actionEdit($id) { // ... implementation } }
在使用演示者注解时请注意,注解是继承的,并且从基类到派生类的顺序进行检查。
注解中的表达式与 isGranted
中的表达式相同,但您还可以访问所有当前请求参数作为变量,并且对象变量包含当前请求。因此,如果您使用将演示者方法参数从 id
转换为实际对象的某些东西,例如添加额外的请求变量 zycon42/param-converters
,您将能够编写:
class PostPresenter extends SecuredPresenter { // ... some code /** * @Security("hasPermission(post, 'EDIT')") */ public function actionEdit(Post $post) { // ... implementation } }
配置
在此处您可以找到可能的配置选项及其默认值。
security: decisionManager: strategy: affirmative allowIfAllAbstain: false allowIfEqualGrantedDenied: true voters: role: on authenticated: on expression: on roleHierarchy: false
在 roleHierarchy
部分中,您可以定义角色如何相互继承。
security: roleHierarchy: ADMIN: { USER, MANAGER } MANAGER: { USER, CLIENT } CLIENT: GUEST
请注意,由于 ADMIN 通过 MANAGER 继承自 USER,所以从 USER 继承自 ADMIN 是多余的。但是,这里有每个角色的有效列表:
- ADMIN: ADMIN, USER, MANAGER, CLIENT, GUEST
- MANAGER: MANAGER, USER, CLIENT, GUEST
- CLIENT: CLIENT, GUEST