安全

编辑该页面

警告:你浏览的文档欧宝体育电话<一个href="//www.oldmanjams.com/releases/5.0">欧宝娱乐app下载地址Symfony 5.0,不再维护。

读<一个href="//www.oldmanjams.com/doc/current/security.html">这个页面的更新版本Symf欧宝娱乐app下载地址ony 6.2(当前的稳定版本)。

< /div>

安全< /h1>

截屏视频

你喜欢视频教程?检查<一个href="https://symfonycasts.com/screencast/symfony-security" class="reference external" rel="external noopener noreferrer" target="_blank">欧宝娱乐app下载地址Symfony安全视频系列

< /div>

欧宝娱乐app下载地址Symfony的安全系统是非常强大的,但是它也可以令人费解的设置。别担心!在本文中,您将了解如何设置应用程序的安全系统一步一步:

  1. 安装安全支持;
  2. 创建您的用户类;
  3. 身份验证和防火墙;
  4. 拒绝访问您的应用程序(授权);
  5. 获取当前用户对象

其他一些重要的话题进行了讨论。

2)创建用户类< /h2>

不管如何你会进行身份验证(例如登录表单或API令牌)在哪里你的用户数据将存储(数据库、单点登录),下一步是总是相同的:创建一个“用户”类。最简单的方法是使用<一个href="//www.oldmanjams.com/doc/current/bundles/SymfonyMakerBundle/index.html" class="reference external">MakerBundle

假设您想要将用户数据存储在数据库的原则:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
美元php bin /控制台:用户安全用户类的名称(例如用户)[用户]:>用户你想存储用户数据数据库(通过学说)吗?(yes / no)[是]:>是的输入属性名称将是独一无二的“显示”的名字用户(例如电子邮件、用户名、uuid(电子邮件)>电子邮件这个程序需要哈希/检查用户密码?(yes / no)[是]:>是的创建:src /实体/用户。php创建:src /仓库/ UserRepository。php更新:src /实体/用户。php updated: config/packages/security.yaml< /code>

就是这样!命令问几个问题,以便它可以生成正是你需要的。最重要的是User.php文件本身。的只有规则对你用户类是它必须实现<一个href="https://github.com/symfony/symfony/blob/5.0/src/Symfony/Component/Security/Core/User/UserInterface.php" class="reference external" title="用户界面" rel="external noopener noreferrer" target="_blank">用户界面。你可以随意添加任何你需要其他领域或逻辑。如果你的用户类是一个实体(如在本例中),您可以使用<一个href="//www.oldmanjams.com/doc/5.0/doctrine.html" class="reference internal">:实体命令添加更多的字段。同时,一定要让新实体和运行迁移:

1 2
美元php bin /控制台:迁移美元php bin /控制台学说:迁移:迁移

2 c)编码的密码< /h2>

并不是所有的应用程序都需要密码的“用户”。如果用户有密码,你可以控制这些密码是如何编码的security.yaml。的:用户命令将预配置你这样做:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11
#配置/包/ security.yaml安全:#……编码器:#使用您的用户类的名字应用实体\ \用户:#使用本机密码编码器#这个值自动选择最好的散列算法#(例如钠可用时)。算法:汽车

现在,Symfon欧宝娱乐app下载地址y知道如何你想要编码的密码,您可以使用UserPasswordEncoderInterface服务之前保存你的用户数据库。

例如,通过使用<一个href="//www.oldmanjams.com/doc/5.0/testing/database.html" class="reference internal">DoctrineFixturesBundle,您可以创建虚拟数据库用户:

1 2 3 4
美元php bin /控制台:夹具装置创建的类名(例如AppFixtures): > UserFixtures

使用此服务编码的密码:

1 2 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
/ / src / DataFixtures / UserFixtures.php+使用Sym欧宝娱乐app下载地址fony核心组件\ \安全\ \编码器\ UserPasswordEncoderInterface;/ /……类UserFixtures延伸夹具{+私人passwordEncoder美元;+公共职能__construct (UserPasswordEncoderInterface passwordEncoder美元)+ {+ $ this - > passwordEncoder = $ passwordEncoder;+}公共函数加载(ObjectManager经理美元){$ user =新用户();/ /……+ $用户向setPassword ($ this - > - > passwordEncoder - > encodePassword (+ $ user,+“the_new_password”+));/ /……}}

您可以手动编码密码通过运行:

1
美元php安全:bin /控制台encode-password

3)认证和防火墙< /h2>

安全系统中配置配置/包/ security.yaml。的大多数重要的部分是防火墙:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8
#配置/包/ security.yaml安全:防火墙:戴夫:模式:^ /(_(分析器| wdt) | css |图片| js) /安全:主要:匿名:懒惰的

“防火墙”是你的认证系统:配置低于它定义了如何用户将能够进行身份验证(例如登录表单,API的令牌,等等)。

只有一个防火墙是活跃在每个请求:Symfony使用欧宝娱乐app下载地址模式找到第一个匹配的关键(你也可以<一个href="//www.oldmanjams.com/doc/5.0/security/firewall_restriction.html" class="reference internal">比赛由主机或其他的东西)。的dev防火墙是一个假的防火墙:它只是确保你不意外块Symfony的开发工具——生活在url欧宝娱乐app下载地址/ _profiler/ _wdt

所有真正的url的处理主要防火墙(不模式关键是它匹配所有url)。防火墙可以有许多的身份验证模式,换句话说很多方面问“你是谁?”的问题。通常,用户是未知的(即没有登录),当他们第一次访问你的网站。的匿名模式,如果启用,用于这些请求。

事实上,如果你现在去主页,你访问,你会发现你“身份验证”不久。。防火墙,它不知道你的身份验证,所以,你是匿名的:

这意味着任何请求都可以有一个匿名的令牌访问一些资源,虽然一些行为(即一些页面或按钮)仍然可以要求特定的特权。一个用户可以访问登录未经身份验证的一种形式作为一种独特的用户(否则无限重定向循环会要求用户进行身份验证,而试图这样做)。

稍后您将了解如何拒绝访问特定的url,控制器,或部分模板。

提示

懒惰的匿名的方式阻止会话开始如果没有必要授权(即显式检查用户特权)。这是很重要的保持请求缓存(参见<一个href="//www.oldmanjams.com/doc/5.0/http_cache.html" class="reference internal">HTTP缓存)。

< /div>

请注意

如果您没有看到工具栏,安装<一个href="//www.oldmanjams.com/doc/5.0/profiler.html" class="reference internal">分析器:

1
美元作曲家要求- dev symfony / pr欧宝娱乐app下载地址ofiler-pack

现在,我们了解我们的防火墙,下一步是创建一个为您的用户进行身份验证!

3 b)对用户进行身份验证< /h2>

身份验证在Symfony会觉得有点“欧宝娱乐app下载地址魔法”。这是因为,而不是建立一个路线&控制器来处理登录,你会激活一个身份验证提供者:一些代码,自动运行之前你的控制器。

欧宝娱乐app下载地址Symfony有几个<一个href="//www.oldmanjams.com/doc/5.0/security/auth_providers.html" class="reference internal">内置的身份验证提供者。如果你的用例匹配其中一个完全,太好了!但是,在大多数情况下——包括一个登录表单我们建议建立一个身份:一个类,它允许您控制每一个身份验证过程的一部分(参见下一节)。

4)拒绝访问,其他角色和授权< /h2>

用户现在可以登录到应用程序使用您的登录表单。太棒了!现在,你需要学习如何与用户拒绝访问和工作对象。这就是所谓的授权,它的工作就是决定如果一个用户可以访问一些资源(一个URL、一个模型对象,一个方法调用,…)。

授权的过程有两个不同的方面:

  1. 用户登录时收到一组特定的角色(如。ROLE_ADMIN)。
  2. 你添加代码,这样一个资源(如URL,控制器)需要一个特定的“属性”(最常见的一个角色ROLE_ADMIN)来访问。

添加代码拒绝访问< /h3>

两个拒绝访问一些方法:

  1. 在security.yaml access_control允许你保护URL模式(如。/管理/ *)。简单,灵活的更少;
  2. 在你的控制器(或其他代码)

获取URL模式(access_control)< /h4>

最基本的保障的一部分,你的应用程序是安全的一个完整的URL模式security.yaml。例如,要求ROLE_ADMIN开始的所有url/管理,您可以:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#配置/包/ security.yaml安全:#……防火墙:#……主要:#……access_control:#需要ROLE_ADMIN / admin *- - - - - -{路径:“^ /管理”,角色:ROLE_ADMIN}#或者需要ROLE_ADMIN或IS_AUTHENTICATED_FULLY / admin *- - - - - -{路径:“^ /管理”,角色:[IS_AUTHENTICATED_FULLY,ROLE_ADMIN]}#“路径”的值可以是任何有效的正则表达式#(这个匹配的url / api / post / 7298和/ api /评论/ 528491)- - - - - -{路径:^ / api / (post) |评论/ \ d + $,角色:ROLE_USER}

你可以定义你需要尽可能多的URL模式——每一个正则表达式。,只有一个将匹配的每个请求:Symfony启动顶部的列表和停止当找到欧宝娱乐app下载地址第一个匹配:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10
#配置/包/ security.yaml安全:#……access_control:# /管理/用户/ *匹配- - - - - -{路径:' ^ /管理/用户的,角色:ROLE_SUPER_ADMIN}#匹配/ admin / *除了任何匹配上述规则- - - - - -{路径:“^ /管理”,角色:ROLE_ADMIN}

将路径与^意味着只有url开始模式匹配。例如,一个路径/管理(没有^)将匹配/管理/ foo但也会匹配的url/ foo /管理

每一个access_control还可以匹配的IP地址、主机名和HTTP方法。它也可以用于将用户重定向到https版本的URL模式。看到<一个href="//www.oldmanjams.com/doc/5.0/security/access_control.html" class="reference internal">安全access_control是如何工作的呢?

保护控制器和其他代码< /h4>

你可以从内部控制器:拒绝访问

1 2 3 4 5 6 7 8 9 10
/ / src /控制器/ AdminController.php/ /……公共函数adminDashboard(){美元- >denyAccessUnlessGranted (“ROLE_ADMIN”);/ /或添加一个可选的消息——被开发人员美元- >denyAccessUnlessGranted (“ROLE_ADMIN”,,用户试图访问一个页面没有ROLE_ADMIN”);}

就是这样!如果不允许访问,特别<一个href="https://github.com/symfony/symfony/blob/5.0/src/Symfony/Component/Security/Core/Exception/AccessDeniedException.php" class="reference external" title="AccessDeniedException" rel="external noopener noreferrer" target="_blank">AccessDeniedException被执行,没有更多的代码在你的控制器。然后,会发生两件事之一:

  1. 如果用户尚未登录,他们将被要求登录(如重定向到登录页面)。
  2. 如果用户登录,但是ROLE_ADMIN的角色,他们会显示403年拒绝访问页面(您可以<一个href="//www.oldmanjams.com/doc/5.0/controller/error_pages.html" class="reference internal">定制)。

由于SensioFrameworkExtraBundle,你也可以获得你的控制器使用注释:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/ / src /控制器/ AdminController.php/ /……+使用Sensio赞助\包\ FrameworkExtraBundle \ \ IsGranted配置;+ / * *+ *要求ROLE_ADMIN *每*控制器方法在这类。+ *+ * @IsGranted (“ROLE_ADMIN”)+ * /类AdminController延伸AbstractController {+ / * *+ *只需要ROLE_ADMIN这个控制器方法。+ *+ * @IsGranted (“ROLE_ADMIN”)+ * /公共函数adminDashboard () {/ /……}}

有关更多信息,请参见<一个href="//www.oldmanjams.com/doc/current/bundles/SensioFrameworkExtraBundle/index.html" class="reference external">FrameworkExtraBundle文欧宝体育电话档

个人用户权限设置< /h3>

大多数应用程序需要更具体的访问规则。例如,用户应该能够编辑他们自己的评论一个博客。选民让你写无论您需要确定访问业务逻辑。使用这些选民类似于实现的基于角色的访问检查前面的章节。读<一个href="//www.oldmanjams.com/doc/5.0/security/voters.html" class="reference internal">如何使用选民来检查用户的权限学习如何实现自己的选民。

< /div>

注销< /h2>

启用日志记录,激活注销配置参数下防火墙:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11 12
#配置/包/ security.yaml安全:#……防火墙:主要:#……注销:路径:app_logout#在注销后重定向#目标:app_any_route

接下来,您将需要创建一个路线这个URL(但不是一个控制器):

  • 注释
  • YAML
  • XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/ / src /控制器/ SecurityController.php名称空间应用程序\控制器;使用欧宝娱乐app下载地址\\FrameworkBundle\控制器\AbstractController;使用欧宝娱乐app下载地址\组件\路由\注释\路线;SecurityController扩展AbstractController{/ * * *@Route(name = " /注销”“app_logout”方法={“获得”})* /公共函数注销(){/ /控制器可以空白:它永远不会执行!\异常(‘\ ' t忘记激活security.yaml注销”);}}

这是它!通过发送一个用户app_logout路线(即/注销Sy欧宝娱乐app下载地址mfony将un-authenticate当前用户重定向。

提示

需要更多的控制注销后会发生什么?添加一个success_handler关键在注销点到一个服务id类的实现<一个href="https://github.com/symfony/symfony/blob/5.0/src/Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.php" class="reference external" title="LogoutSuccessHandlerInterface" rel="external noopener noreferrer" target="_blank">LogoutSuccessHandlerInterface

< /div>

层次的角色< /h2>

而不是给每个用户很多角色,您可以通过创建一个定义角色继承规则角色层次结构:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7
#配置/包/ security.yaml安全:#……role_hierarchy:ROLE_ADMIN:ROLE_USERROLE_SUPER_ADMIN:[ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH]

用户提供的ROLE_ADMIN也会有作用ROLE_USER的角色。和用户ROLE_SUPER_ADMIN,会自动ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCHROLE_USER(继承自ROLE_ADMIN)。

角色层次的工作,不要试图调用$ user - >将getRoles ()手动。例如,在一个扩展的控制器<一个href="//www.oldmanjams.com/doc/5.0/controller.html" class="reference internal">基本控制器:

1 2 3 4 5 6
/ /坏- $ user - >将getRoles()将不知道角色的层次结构美元hasAccess= in_array (“ROLE_ADMIN”,美元用户- >将getRoles ());/ /好——正常安全的使用方法美元hasAccess=美元- >isGranted (“ROLE_ADMIN”);美元- >denyAccessUnlessGranted (“ROLE_ADMIN”);

请注意

role_hierarchy值是静态的,你不能,例如,角色层次结构存储在一个数据库中。如果你需要创建一个定制的<一个href="//www.oldmanjams.com/doc/5.0/security/voters.html" class="reference internal">安全选民查找数据库中的用户角色。

< /div>

常见问题< /h2>
我可以有多个防火墙吗?
是的!但这通常是没有必要的。每个防火墙就像一个独立的安全系统。因此,除非你有非常不同的身份验证需求,一个防火墙通常工作得很好。与<一个href="//www.oldmanjams.com/doc/5.0/security/guard_authentication.html" class="reference internal">后卫的身份验证,您可以创建各种不同的方法使认证(如表单登录、API密钥身份验证和LDAP)都在相同的防火墙。
我可以之间共享验证防火墙吗?
是的,但只有一些配置。如果你对一个防火墙,使用多个防火墙和您进行身份验证自动验证对任何其他防火墙。不同的防火墙就像不同的安全系统。要做到这一点,你必须显式地指定相同的<一个href="//www.oldmanjams.com/doc/5.0/reference/configuration/security.html" class="reference internal">安全配置引用(SecurityBundle)对于不同的防火墙。但是通常对于大多数应用程序,有一个主要的防火墙就足够了。
安全工作似乎并不在我的错误页面
路由是做之前安全,不受任何防火墙404错误页面。这意味着你不能检查安全甚至访问这些页面上的用户对象。看到<一个href="//www.oldmanjams.com/doc/5.0/controller/error_pages.html" class="reference internal">如何自定义错误页面吗为更多的细节。
似乎我的身份验证不工作:没有错误,但是我从来没有登录
有时认证可能是成功的,但重定向后,你立即注销由于加载问题用户从会话。是否这是一个问题,检查你的日志文件(var / log / dev.log的日志信息:
无法刷新令牌,因为用户已经改变了
如果你看到这个,可能有两个原因。首先,可能会有一个问题加载用户的会话。看到<一个href="//www.oldmanjams.com/doc/5.0/security/user_provider.html" class="reference internal">安全的用户提供。第二,如果某些数据库中的用户信息改变了自从上次刷新页面,Symfony会故意注销用户出于安全原因。欧宝娱乐app下载地址

这项工作,包括代码示例,许可下<一个rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons冲锋队3.0许可证。

Symfony专家欧宝娱乐app下载地址认可

Symfony专家欧宝娱乐app下载地址认可< /p>< /div>