安全

编辑本页

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

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

安全

欧宝娱乐app下载地址Symfony的安全系统非常强大,但设置起来也很麻烦。在本章中,您将学习如何逐步设置应用程序的安全性,从配置防火墙和如何加载用户到拒绝访问和获取User对象。根据您的需要,有时初始设置可能会很困难。但一旦完成,Symfony的安全系统既灵欧宝娱乐app下载地址活,(希望)使用起来很有趣。

由于有很多内容要讲,本章被组织成几个大的部分:

  1. 最初的security.yml设置(身份验证);
  2. 拒绝访问你的应用程序(授权);
  3. 获取当前User对象。

这些之后是一些小的(但仍然迷人的)部分,如<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">注销而且<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">编码用户密码

1)初始安全性。yml设置(认证)

安全系统配置在应用程序/配置/ security.yml.默认配置如下所示:

  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13
# app / config / security.yml安全:提供者:in_memory:记忆:防火墙:戴夫:模式:^ /(_(分析器| wdt) | css |图片| js) /安全:默认值:匿名:

防火墙关键是您的安全配置。的dev防火墙并不重要,它只是确保Symfony的开发工具——这些工具存在于像欧宝娱乐app下载地址/ _profiler而且/ _wdt不会被你的安保人员阻止。

方法处理所有其他url默认的防火墙(不模式键表示匹配所有url)。您可以将防火墙视为安全系统,因此通常只有一个主防火墙是有意义的。但这确实是意味着每个URL都需要身份验证匿名Key负责这个。事实上,如果你现在去主页,你就可以访问,你会看到你被“认证”为不久。.不要被Authenticated旁边的“是”所迷惑,你只是一个匿名用户:

稍后您将学习如何拒绝对某些url或控制器的访问。

提示

安全是高度可配置的,有一个<一个href="//www.oldmanjams.com/doc/2.3/reference/configuration/security.html" class="reference internal">安全配置参考它显示了所有选项,并给出了一些额外的解释。

A)配置用户的身份验证方式

防火墙的主要工作是配置如何您的用户将进行身份验证。他们会使用登录表单吗?HTTP基本认证?API令牌?以上都是吗?

让我们从HTTP基本身份验证(老式的提示符)开始,从这里开始。要激活此功能,请添加http_basic防火墙下的关键字:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9
# app / config / security.yml安全:#……防火墙:#……默认值:匿名:http_basic:

简单!要尝试这一点,您需要要求用户登录才能查看页面。为了让事情变得有趣,在/管理.例如,如果你使用注释,可以创建这样的东西:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ / src / AppBundle /控制器/ DefaultController.php/ /……使用Sensio赞助FrameworkExtraBundle配置路线使用欧宝娱乐app下载地址组件HttpFoundation响应DefaultController扩展控制器/ * * *@Route(" / admin ") * /公共函数adminAction()返回响应(身体的< html > < > Admin页面!< /身体> < / html >”);}}

接下来,添加一个access_control进入security.yml需要用户登录才能访问这个URL:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11
# app / config / security.yml安全:#……防火墙:#……默认值:#……access_control:#需要/admin*的ROLE_ADMIN-路径:^ /管理,角色:ROLE_ADMIN

请注意

你会学到更多ROLE_ADMIN然后拒绝访问<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">安全部分。

太棒了!现在,如果你去/管理,你会看到HTTP基本认证提示:

但是你能以谁的身份登录呢?用户来自哪里?

提示

想要使用传统的登录表单?太棒了!看到<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/form_login_setup.html" class="reference internal">如何建立一个传统的登录表单.还支持哪些其他方法?看到<一个href="//www.oldmanjams.com/doc/2.3/reference/configuration/security.html" class="reference internal">配置引用或<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/custom_authentication_provider.html" class="reference internal">建立自己的

提示

如果您的应用程序通过第三方服务(如谷歌、Facebook或Twitter)登录用户,请检查<一个href="https://github.com/hwi/HWIOAuthBundle" class="reference external" rel="external noopener noreferrer" target="_blank">HWIOAuthBundle欧宝下载链接社区包。

B)配置如何加载用户

当您输入用户名时,Symfony需要从某个地方加载该用户的信息。欧宝娱乐app下载地址这被称为“用户提供者”,您负责配置它。欧宝娱乐app下载地址Symfony有一个内置的方法<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/entity_provider.html" class="reference internal">从数据库加载用户,或者你可以<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/custom_provider.html" class="reference internal">创建自己的用户提供程序

最简单(但最受限制)的方法是配置Symfony以直接从欧宝娱乐app下载地址security.yml文件本身。这被称为“内存中”提供程序,但最好将其视为“配置中”提供程序:

  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13
# app / config / security.yml安全:提供者:in_memory:记忆:用户:雷恩:密码:ryanpass角色:“ROLE_USER”管理:密码:小猫角色:“ROLE_ADMIN”#……

防火墙,你可以有多个供应商,但你可能只需要一个。如果你有多个,你可以配置哪个一个提供程序用于您的防火墙提供者(如关键。提供者:in_memory).

另请参阅

看到<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/multiple_user_providers.html" class="reference internal">如何使用多个用户提供程序有关多个提供者设置的所有详细信息。

尝试使用用户名登录管理和密码小猫.您应该看到一个错误!

帐号“Symfony\组件\安全\核心\用户\用户”没有配置编码器欧宝娱乐app下载地址

若要修复此问题,请添加编码器关键:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7
# app / config / security.yml安全:#……编码器:欧宝娱乐app下载地址Symfony核心组件\ \安全\ \ \用户:明文#……

用户提供程序加载用户信息并将其放入用户对象。如果你<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/entity_provider.html" class="reference internal">从数据库加载用户或<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/custom_provider.html" class="reference internal">其他来源,您将使用自己的自定义User类。但是当你使用"in memory"提供程序时,它会给你一个欧宝娱乐app下载地址\组件\安全\核心\用户\用户对象。

无论您的User类是什么,您都需要告诉Symfony使用什么算法来编码密码。欧宝娱乐app下载地址在本例中,密码只是明文,但稍后将更改为使用bcrypt

如果您现在刷新,您将登录!web调试工具栏甚至会告诉你你是谁,你有什么角色:

因为这个URL需要ROLE_ADMIN,如果您以瑞安,这将拒绝您访问。稍后会详细介绍(<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">安全).

C)对用户密码进行编码

您的用户是否存储在security.yml,在数据库或其他地方,你会想要编码他们的密码。最好的算法是bcrypt

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8
# app / config / security.yml安全:#……编码器:欧宝娱乐app下载地址Symfony核心组件\ \安全\ \ \用户:算法:bcrypt成本:12

谨慎

如果使用的是PHP 5.4或更低版本,则需要安装ircmaxell / password-compat库,以便能够使用bcrypt编码器:

1
$ composer需要ircmaxell/password-compat“~ 1.0”

当然,用户的密码现在需要使用这种精确的算法进行编码。对于硬编码用户,可以使用<一个href="https://www.dailycred.com/blog/12/bcrypt-calculator" class="reference external" rel="external noopener noreferrer" target="_blank">在线工具(因为这是一个公共工具,避免使用真实的密码)。

它会给你这样的东西:

  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14
# app / config / security.yml安全:#……提供者:in_memory:记忆:用户:雷恩:密码:2美元12美元LCY0MefVIEc3TYPHV9SNnuzOfyr2p / AXIGoQJEDs4am4JwhNz / jli角色:“ROLE_USER”管理:密码:2美元$ cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7 / flCM3V0G 12美元角色:“ROLE_ADMIN”

现在一切都和以前一样了。但是如果您有动态用户(例如来自数据库),如何在将密码插入数据库之前以编程方式对密码进行编码?别担心,看<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">安全获取详细信息。

提示

此方法支持的算法取决于您的PHP版本,但包括PHP函数返回的算法<一个href="https://secure.php.net/manual/en/function.hash-algos.php" class="reference external" title="hash_algos" rel="external noopener noreferrer" target="_blank">hash_algos以及其他一些(例如bcrypt)。看到编码器输入<一个href="//www.oldmanjams.com/doc/2.3/reference/configuration/security.html" class="reference internal">保安参考组为例子。

2)拒绝访问、角色和其他授权

用户现在可以使用http_basic或者其他方法。太棒了!现在,您需要学习如何拒绝访问并使用User对象。这叫做授权,它的任务是决定用户是否可以访问某些资源(URL、模型对象、方法调用等等)。

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

  1. 用户在登录时接收到一组特定的角色(例如:ROLE_ADMIN).
  2. 您可以添加代码,以便资源(例如URL,控制器)需要特定的“属性”(最常见的是像这样的角色)ROLE_ADMIN)以供查阅。

提示

除了角色(例如。ROLE_ADMIN),您可以使用其他属性/字符串来保护资源(例如:编辑),并使用投票人或Symfony的ACL欧宝娱乐app下载地址系统来赋予这些含义。如果你需要检查用户A是否可以“编辑”某个对象B(例如id为5的产品),这可能会很方便<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">安全

添加代码拒绝访问

两个拒绝访问某物的方法:

  1. 在security.yml中的访问控制允许你保护URL模式(例如:/管理/ *).这很容易,但缺乏灵活性;
  2. 在你的代码中通过安全。上下文服务

保护URL模式(access_control)

保护部分应用程序的最基本方法是保护整个URL模式。您在前面看到了这个,其中任何匹配正则表达式的内容^ /管理要求ROLE_ADMIN角色:

  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12
# app / config / security.yml安全:#……防火墙:#……默认值:#……access_control:#需要/admin*的ROLE_ADMIN-路径:^ /管理,角色:ROLE_ADMIN

这对于保护整个区域是很好的,但你可能也想这样做<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">保护您的单个控制器

您可以根据需要定义任意数量的URL模式—每个都是一个正则表达式。,只有一个将被匹配。欧宝娱乐app下载地址Symfony将从顶部开始查看每一个,一旦发现一个就立即停止access_control匹配URL的条目。

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7
# app / config / security.yml安全:#……access_control:-路径:^ /管理/用户,角色:ROLE_SUPER_ADMIN-路径:^ /管理,角色:ROLE_ADMIN

在路径前面加上意味着只有url开始与图案相匹配。例如,简单的路径/管理(没有)会相配/管理/ foo但也会匹配url/ foo /管理

access_controlSection非常强大,但如果您不理解,它也可能是危险的(因为它涉及到安全性)如何它的工作原理。除了URL之外,access_control可以匹配IP地址,主机名和HTTP方法。还可以使用它将用户重定向到httpsURL模式的版本。

要了解所有这些,请参见<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/access_control.html" class="reference internal">安全访问控制如何工作?

检查用户是否已登录(IS_AUTHENTICATED_FULLY)

到目前为止,您已经根据角色(以这些字符串开头)检查了访问权限具备ROLE_并分配给用户。但是如果你只有想要检查用户是否已登录(您不关心角色),然后可以使用IS_AUTHENTICATED_FULLY

1 2 3 4 5 6 7 8 9 10 11
/ /……使用欧宝娱乐app下载地址组件安全核心异常AccessDeniedException公共函数helloAction的名字如果(!->get (“security.context”->isGranted (“IS_AUTHENTICATED_FULLY”)) {AccessDeniedException ();}/ /……

提示

当然你也可以在access_control

IS_AUTHENTICATED_FULLY不是一个角色,但它有点像一个角色,每个成功登录的用户都会有这个。事实上,像这样的特殊属性有三个:

  • IS_AUTHENTICATED_REMEMBERED所有登录用户有这个,即使他们登录是因为一个“记住我的cookie”。即使你不使用<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/remember_me.html" class="reference internal">记住我的功能,您可以使用此命令检查用户是否已登录。
  • IS_AUTHENTICATED_FULLY:这类似于IS_AUTHENTICATED_REMEMBERED,但更强。仅因为“记住我的cookie”而登录的用户将有IS_AUTHENTICATED_REMEMBERED但不会有IS_AUTHENTICATED_FULLY
  • IS_AUTHENTICATED_ANONYMOUSLY所有用户(甚至是匿名用户)都有这个功能——当白名单url,以保证访问-一些细节<一个href="//www.oldmanjams.com/doc/2.3/cookbook/security/access_control.html" class="reference internal">安全访问控制如何工作?

检索用户对象

认证后,用户对象可以通过security.context服务。在控制器内部,这看起来像:

1 2 3 4 5 6 7 8 9 10 11
公共函数indexAction()如果(!->get (“security.context”->isGranted (“IS_AUTHENTICATED_FULLY”)) {AccessDeniedException ();}用户->getUser ();//上面是一个快捷方式用户->get (“security.context”->getToken ()->getUser ();}

提示

用户将是一个对象,该对象的类将取决于您的<一个href="//www.oldmanjams.com/doc/2.3/book/security.html" class="reference internal">用户提供者

现在你可以调用任何打开的方法你的用户对象。例如,如果你的User对象有一个getFirstName ()方法,你可以使用它:

1 2 3 4 5 6 7 8 9
使用欧宝娱乐app下载地址组件HttpFoundation响应/ /……公共函数indexAction()/ /……返回响应("你好"用户->getFirstName ());}

注销

通常,您还希望用户能够注销。幸运的是,防火墙可以在您激活注销配置参数:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10
# app / config / security.yml安全:#……防火墙:secured_area:#……注销:路径:/注销目标:/

接下来,你需要为这个URL创建一个路由(但不是控制器):

  • YAML
  • XML
1 2 3
# app / config / routing.yml注销:路径:/注销

就是这样!通过将用户发送到/注销(或者你配置的路径), Symfo欧宝娱乐app下载地址ny将取消当前用户的身份验证。

方法所定义的路径被重定向到目标参数(例如主页).

提示

如果在登出后需要做一些更有趣的事情,可以通过添加success_handler键并将其指向实现的类的服务id<一个href="https://github.com/symfony/symfony/blob/2.3/src/Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.php" class="reference external" title="LogoutSuccessHandlerInterface" rel="external noopener noreferrer" target="_blank">LogoutSuccessHandlerInterface.看到<一个href="//www.oldmanjams.com/doc/2.3/reference/configuration/security.html" class="reference internal">安全配置参考

谨慎

请注意,在使用http-basic身份验证的防火墙时,没有真正的注销方法:唯一的方法是注销就是让浏览器停止在每次请求时发送您的姓名和密码。清理浏览器缓存或重新启动浏览器通常会有帮助。一些web开发工具可能也会有帮助。

密码动态编码

请注意

由于历史原因,Symfony使用了这个术语欧宝娱乐app下载地址“密码编码”当它真的应该指“密码哈希”.编码器实际上是<一个href="https://en.wikipedia.org/wiki/Cryptographic_hash_function" class="reference external" rel="external noopener noreferrer" target="_blank">密码哈希函数

例如,如果要在数据库中存储用户,则需要在插入用户密码之前对其进行编码。无论你为你的用户对象配置什么算法,哈希密码总是可以通过以下方式从控制器确定:

1 2 3 4 5 6 7
工厂->get (“security.encoder_factory”);//你的用户对象是什么用户AppBundle \ \用户实体();编码器工厂->getEncoder (用户);密码编码器->encodePassword (“ryanpass”用户->getSalt ());用户->向setPassword (密码);

为了让它工作,只要确保你有编码器为你的用户类(例如。实体AppBundle \ \用户)根据编码器关键在应用程序/配置/ security.yml

美元的编码器对象也具有isPasswordValid方法,该方法采用用户对象作为第一个参数,要检查的普通密码作为第二个参数。

谨慎

当您允许用户提交明文密码(例如,注册表单,更改密码表单)时,您将必须进行验证,确保密码不超过4096个字符。详情请参阅<一个href="//www.oldmanjams.com/doc/2.3/cookbook/doctrine/registration_form.html" class="reference internal">如何使用简单的注册表格

无状态的验证

默认情况下,Symfon欧宝娱乐app下载地址y依赖cookie (Session)来持久保存用户的安全上下文。但是,如果使用证书或HTTP身份验证,则不需要持久性,因为每个请求都可以使用凭据。在这种情况下,如果你不需要在请求之间存储任何其他东西,你可以激活无状态身份验证(这意味着Symfony不会创建任何cookie):欧宝娱乐app下载地址

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8
# app / config / security.yml安全:#……防火墙:主要:http_basic:无状态:真正的

请注意

如果您使用表单登录,Symfony将创建一个coo欧宝娱乐app下载地址kie,即使您设置无状态的真正的

此工作,包括代码示例,是根据<一个rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">创作共用BY-SA 3.0许可证。