如何使用选民检查用户权限
编辑本页如何使用选民检查用户权限
选民是Symfony管ob娱乐下载理权限的最强大的方式。它们允许您集中所有权限逻辑,然后在许多地方重用它们。
然而,如果你不重用权限或者你的规则是基本的,你总是可以把逻辑直接放到你的控制器中。下面是一个例子,如果你想让一个路由只对“所有者”可访问:
1 2 3 4 5 6 7
/ / src /控制器/ PostController.php/ /……//在你的控制器动作如果($帖子->getOwner () = =$这->getUser ()) {扔$这->createAccessDeniedException ();}
从这个意义上讲,本页所使用的下面的例子对于选民来说是一个最小的例子。
下面是Symfony与ob娱乐下载投票人的工作方式:每次使用isGranted ()
方法的授权检查器或调ob娱乐下载用denyAccessUnlessGranted ()
在控制器中(使用授权检查器),或通过访问控制.
最终,Symfony从所ob娱乐下载有投票人那里得到反馈,并根据这些反馈做出最终决定(允许或拒绝访问资源)应用程序中定义的策略,可以是肯定的、一致的、一致的或优先的。
选民界面
需要实现的自定义投票人VoterInterface或扩展选民,这使得创建投票者更加容易:
1 2 3 4 5 6 7 8
使用ob娱乐下载\组件\安全\核心\身份验证\令牌\TokenInterface;使用ob娱乐下载\组件\安全\核心\授权\选民\VoterInterface;摘要类选民实现了VoterInterface{摘要受保护的函数支持(字符串$属性、混合$主题):保龄球;摘要受保护的函数voteOnAttribute(字符串$属性、混合$主题, TokenInterface$令牌):保龄球;}
提示
对于执行大量权限检查的应用程序来说,多次检查每个投票人可能会很耗时。在这些情况下,要提高性能,可以让投票人实现CacheableVoterInterface.这允许访问决策管理器记住投票人支持的主题的属性和类型,以便每次只调用所需的投票人。
设置:检查控制器中的访问
假设你有一个帖子
对象,您需要决定当前用户是否可以编辑或视图对象。在你的控制器中,你会用这样的代码检查访问:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/ / src /控制器/ PostController.php/ /……类为PostController扩展AbstractController{#[路由('/posts/{id}',名称:'post_show')]公共函数显示($id):响应{//获取Post对象——例如查询它$帖子=……;// check for "view" access:调用所有投票人$这->denyAccessUnlessGranted (“视图”,$帖子);/ /……}#[Route('/posts/{id}/edit', name: 'post_edit')]公共函数编辑($id):响应{//获取Post对象——例如查询它$帖子=……;//检查“edit”权限:调用所有投票人$这->denyAccessUnlessGranted (“编辑”,$帖子);/ /……}}
的denyAccessUnlessGranted ()
方法(以及isGranted ()
方法)调用“voter”系统。现在,没有选民会投票决定用户是否可以“查看”或“编辑”一个帖子
.但是你可以创建你的自己的投票人用任何你想用的逻辑来决定。
创建自定义投票人
假设决定用户是否可以“查看”或“编辑”a的逻辑帖子
对象非常复杂。例如,用户
可以随时编辑或查看帖子
他们创造了。如果帖子
被标记为“公共”,任何人都可以查看。这种情况下的投票者应该是这样的:
12 34 56 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
/ / src /安全/ PostVoter.php名称空间应用程序\安全;使用应用程序\实体\帖子;使用应用程序\实体\用户;使用ob娱乐下载\组件\安全\核心\身份验证\令牌\TokenInterface;使用ob娱乐下载\组件\安全\核心\授权\选民\选民;类PostVoter扩展选民{//这些字符串只是被发明出来的:你可以使用任何东西常量视图=“视图”;常量编辑=“编辑”;受保护的函数支持(字符串$属性、混合$主题):保龄球{//如果该属性不是我们支持的,返回false如果(!in_array ($属性, (自我::看来,自我::编辑])){返回假;}//只对Post对象投票如果(!$主题运算符Post) {返回假;}返回真正的;}受保护的函数voteOnAttribute(字符串$属性、混合$主题, TokenInterface$令牌):保龄球{$用户=$令牌->getUser ();如果(!$用户运算符用户){//用户必须登录;如果不是,则拒绝访问返回假;}//你知道$subject是Post对象,这要感谢' supports() '/**@varPost $ Post */$帖子=$主题;返回匹配($属性){自我::视图= >$这->canView ($帖子,$用户),自我::编辑= >$这->canEdit ($帖子,$用户),默认的= >扔新\ LogicException (“不能到达这个密码!”)};}私人函数canView(文章$帖子、用户$用户):保龄球{//如果他们可以编辑,他们可以查看如果($这->canEdit ($帖子,$用户)) {返回真正的;}// Post对象可以有一个方法' isPrivate() '返回!$帖子->isPrivate ();}私人函数canEdit(文章$帖子、用户$用户):保龄球{//假设Post对象有一个' getOwner() '方法返回$用户= = =$帖子->getOwner ();}}
就是这样!投票人完成了!接下来,配置它.
概括一下,下面是对这两个抽象方法的期望:
-
投票人::支持(字符串$属性,混合$主题)
-
当
isGranted ()
(或denyAccessUnlessGranted ()
)调用时,第一个参数在这里传递为美元的属性
(如。ROLE_USER
,编辑
),第二个参数(如果有的话)传递为美元的主题
(如。零
,一个帖子
对象)。您的工作是确定您的投票者是否应该对属性/主题组合进行投票。如果返回true,voteOnAttribute ()
将被调用。否则,你的投票人已经完成了:其他投票人应该处理这个。在本例中,返回真正的
如果属性为视图
或编辑
如果物体是a帖子
实例。 -
voteOnAttribute(字符串$attribute,混合$subject, TokenInterface $token)
-
如果你回来
真正的
从支持()
,则调用此方法。你的任务就是回来真正的
允许访问和假
拒绝访问。的美元的令牌
可用于查找当前用户对象(如果有的话)。在本例中,包含了所有复杂的业务逻辑以确定访问权限。
配置投票者
要将投票人注入安全层,必须将其声明为服务并标记为security.voter
.但是如果你用默认的服务。yaml的配置,这将自动为您完成!当你用view/edit调用isgranting()并传递一个Post对象,您的选民将被呼叫,您可以控制访问。
检查Voter中的角色
如果你想打电话怎么办isGranted ()
从内部您的选民-例如,您想要查看当前用户是否有ROLE_SUPER_ADMIN
.这可以通过注入安全变成你的选民。你可以用这个来,例如,总是允许访问具有的用户ROLE_SUPER_ADMIN
:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/ / src /安全/ PostVoter.php/ /……使用ob娱乐下载\包\SecurityBundle\安全;类PostVoter扩展选民{/ /……私人$安全;公共函数__construct(安全$安全){$这->安全=$安全;}受保护的函数voteOnAttribute($属性、混合$主题, TokenInterface$令牌):保龄球{/ /……// ROLE_SUPER_ADMIN可以做任何事情!的力量!如果($这->安全->isGranted (“ROLE_SUPER_ADMIN”)) {返回真正的;}/ /……这都是正常的选民逻辑}}
如果你在用默认的服务。yaml的配置,你完蛋了!ob娱乐下载Symfony将自动通过security.helper
服务,当实例化你的选民(感谢autotowiring)。
更改访问决策策略
通常情况下,在任何给定的时间内,只有一名选民会投票(其余的选民将“弃权”,这意味着他们将返回投票假
从支持()
).但在理论上,您可以让多个投票者投票支持一个动作和对象。例如,假设有一个投票人检查用户是否是站点的成员,另一个投票人检查用户是否超过18岁。
为了处理这些情况,访问决策管理器使用您可以配置的“策略”。有四种策略可供选择:
-
肯定的
(默认) - 一旦有机会,就会立即授予访问权限一个允许进入的投票人;
-
共识
-
如果允许访问的选民多于拒绝访问的选民,则允许访问。在平局的情况下,决定是基于
allow_if_equal_granted_denied
配置选项(默认为真正的
); -
一致
- 只有当没有选民拒绝访问时,才允许访问。
-
优先级
- 这允许或拒绝第一个没有弃权的选民访问,基于他们的服务优先级;
无论选择哪种策略,如果所有选民都投了弃权票,则该决定是基于allow_if_all_abstain
配置选项(默认为假
).
在上面的场景中,两个投票人都应该授予访问权,以便授予用户阅读文章的访问权。在这种情况下,默认策略不再有效一致
应该改为使用。你可以在安全配置中设置:
- YAML
- XML
- PHP
1 2 3 4 5
#配置/包/ security.yaml安全:access_decision_manager:策略:一致allow_if_all_abstain:假
自定义访问决策策略
如果没有任何内置策略适合您的用例,则定义strategy_service
选项来使用自定义服务(您的服务必须实现AccessDecisionStrategyInterface):
- YAML
- XML
- PHP
1 2 3 4 5
#配置/包/ security.yaml安全:access_decision_manager:strategy_service:App \安全\ MyCustomAccessDecisionStrategy#……
自定义访问决策管理器
如果需要提供完全自定义的访问决策管理器,请定义服务
选项来使用自定义服务作为访问决策管理器(您的服务必须实现AccessDecisionManagerInterface):
- YAML
- XML
- PHP
1 2 3 4 5
#配置/包/ security.yaml安全:access_decision_manager:服务:App \安全\ MyCustomAccessDecisionManager#……