如果你有<一个href="https://www.oldmanjams.com/doc/5.3/setup.html" class="reference internal">欧宝娱乐app下载地址Symfony Flex安装后,还会创建一个security.yaml您的配置文件:

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
#配置/包/ security.yaml安全:enable_authenticator_manager:真正的# https://欧宝娱乐app下载地址www.oldmanjams.com/doc/current/security.html c-hashing-passwordspassword_hashers:欧宝娱乐app下载地址Symfony \ \安全\ \用户\ PasswordAuthenticatedUserInterface核心组件:“汽车”# https://欧宝娱乐app下载地址www.oldmanjams.com/doc/current/security.html where-do-users-come-from-user-providers提供者:users_in_memory:记忆:防火墙:戴夫:模式:^ /(_(分析器| wdt) | css |图片| js) /安全:主要:懒惰:真正的供应商:users_in_memory#激活不同的身份验证方式# https://欧宝娱乐app下载地址www.oldmanjams.com/doc/current/security.html firewalls-authentication# https://欧宝娱乐app下载地址www.oldmanjams.com/doc/current/security/impersonating_user.html# switch_user: true#简单的方法来控制你的网站的大部分访问注意:只有匹配的*第一个*访问控制将被使用access_control:# - {path: ^/admin, roles: ROLE_ADMIN}# - {path: ^/profile, role: ROLE_USER}

这是很多配置!在接下来的章节中,我们将讨论三个主要元素:

用户供应商
应用程序的任何安全部分都需要一些用户概念。用户提供者根据“用户标识符”(例如用户的电子邮件地址)从任何存储(例如数据库)加载用户;
防火墙&<一个href="https://www.oldmanjams.com/doc/5.3/security.html" class="reference internal">用户身份验证防火墙
防火墙是保护应用程序安全的核心。防火墙中的每个请求都将检查它是否需要经过身份验证的用户。防火墙还负责对该用户进行身份验证(例如使用登录表单);
访问控制(授权)access_control
使用访问控制和授权检查器,您可以控制执行特定操作或访问特定URL所需的权限。

谨慎

欧宝娱乐app下载地址Symfony Security在5.3中进行了重大更改。本文将解释新authenticator-based系统(由enable_authenticator_manager:真配置选项)。

请参阅<一个href="https://www.oldmanjams.com/doc/5.2/security.html" class="reference external">本文档5.2版本欧宝体育电话如果你还在用旧的安全系统。

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 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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
/ / src /实体/ User.php名称空间应用程序实体使用应用程序存储库UserRepository使用学说ORM映射作为ORM使用欧宝娱乐app下载地址组件安全核心用户PasswordAuthenticatedUserInterface使用欧宝娱乐app下载地址组件安全核心用户用户界面/ * * *@ORM\实体(repositoryClass = UserRepository::类)* /用户实现了用户界面PasswordAuthenticatedUserInterface/ * * *@ORM\ Id *@ORM\ GeneratedValue *@ORM\列(类型=“整数”)* /私人id/ * * *@ORM\Column(type="string", length=180, unique=true) */私人电子邮件/ * * *@ORM\列(type = " json ") * /私人角色= [];/ * * *@varstring哈希密码* .@ORM\列(type = "字符串")* /私人密码公共函数getId(): ?int返回->id;}公共函数getEmail(): ?字符串返回->电子邮件;}公共函数setEmail(字符串电子邮件自我->电子邮件=电子邮件返回;}/** *用户的公开表示(例如用户名、电子邮件地址等)**@see用户界面* /公共函数getUserIdentifier()字符串返回(字符串)->电子邮件;}/ * * *@deprecated自Symfo欧宝娱乐app下载地址ny 5.3 */公共函数getUsername()字符串返回(字符串)->电子邮件;}/ * * *@see用户界面* /公共函数将getRoles()数组角色->角色;//保证每个用户至少有ROLE_USER角色[] =“ROLE_USER”返回array_unique (角色);}公共函数setRoles(数组角色自我->角色=角色返回;}/ * * *@seePasswordAuthenticatedUserInterface * /公共函数getPassword()字符串返回->密码;}公共函数向setPassword(字符串密码自我->密码=密码返回;}如果你在security.yaml中没有使用现代的哈希算法(例如bcrypt或sodium),则只需要返回一个salt。* *@see用户界面* /公共函数getSalt(): ?字符串返回;}/ * * *@see用户界面* /公共函数eraseCredentials()//如果您在用户上存储了任何临时的敏感数据,请在这里清除// $this->plainPassword = null;}}

5.3

的<一个href="https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/Core/User/PasswordAuthenticatedUserInterface.php" class="reference external" title="PasswordAuthenticatedUserInterface"rel="external noopener noreferrer" target="_blank">PasswordAuthenticatedUserInterface接口和getUserIdentifier ()方法在Symfony 5.3中进行了介绍。欧宝娱乐app下载地址

如果您的用户是Doctrine实体,就像上面的例子一样,不要忘记创建表by<一个href="https://www.oldmanjams.com/doc/5.3/doctrine.html" class="reference internal">创建并运行迁移

1 2
PHP bin/控制台make:迁移PHP bin/控制台原则:迁移:迁移

:用户命令还在安全配置中添加用户提供程序的配置:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9
#配置/包/ security.yaml安全:#……提供者:app_user_provider:实体:类:应用实体\ \用户属性:电子邮件

这个用户提供者知道如何根据“用户标识符”(例如用户的电子邮件地址或用户名)从存储(例如数据库)(重新)加载用户。上面的配置使用Doctrine加载用户实体使用电子邮件属性作为“用户标识符”。

用户提供程序在安全生命周期中的几个地方被使用:

根据标识符加载User
在登录(或任何其他验证程序)期间,提供程序根据用户标识符加载用户。一些其他功能,比如<一个href="https://www.oldmanjams.com/doc/5.3/security/impersonating_user.html" class="reference internal">用户模拟而且<一个href="https://www.oldmanjams.com/doc/5.3/security/remember_me.html" class="reference internal">记得我也要用这个。
从会话中重新加载User
在每个请求开始时,从会话中加载用户(除非您的防火墙是无状态的).提供者“刷新”用户(例如,再次查询数据库以获取新数据),以确保所有用户信息都是最新的(如果有必要,如果有更改,用户将取消身份验证/注销)。看到<一个href="https://www.oldmanjams.com/doc/5.3/security.html" class="reference internal">安全有关此过程的更多信息。

欧宝娱乐app下载地址Symfony有几个内置的用户提供者:

实体用户提供商
从数据库中加载用户<一个href="https://www.oldmanjams.com/doc/5.3/doctrine.html" class="reference internal">学说
LDAP用户提供者
从LDAP服务器加载用户;
内存用户提供商
从配置文件加载用户;
连锁用户提供商
将两个或多个用户提供程序合并为一个新的用户提供程序。

内置的用户提供程序涵盖了应用程序最常见的需求,但您也可以创建自己的应用程序<一个href="https://www.oldmanjams.com/doc/5.3/security/user_providers.html" class="reference internal">定制用户提供程序

请注意

有时,你需要在另一个类中注入用户提供程序(例如,在你的自定义验证器中)。所有用户提供者的服务ID都遵循以下模式:security.user.provider.concrete。< your-provider-name >(< your-provider-name >配置键,例如。app_user_provider).如果只有一个用户提供程序,则可以使用<一个href="https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/Core/User/UserProviderInterface.php" class="reference external" title="UserProviderInterface"rel="external noopener noreferrer" target="_blank">UserProviderInterface类型-hint。

PasswordAuthenticatedUserInterface

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/ / src /实体/ User.php/ /……使用欧宝娱乐app下载地址组件安全核心用户PasswordAuthenticatedUserInterface用户实现了用户界面PasswordAuthenticatedUserInterface/ /……/ * * *@return将此用户的哈希密码字符串*/公共函数getPassword()字符串返回->密码;}}

然后,配置这个类应该使用哪个密码散列器。如果你的security.yaml那么,文件还没有预先配置:用户我应该为你做这些的

1 2 3 4 5 6 7
#配置/包/ security.yaml安全:#……password_hashers:#使用本地密码散列器,它会自动选择和迁移最好的密码#可能的哈希算法(从Symfony 5.3开始,这是“bcrypt”)欧宝娱乐app下载地址欧宝娱乐app下载地址Symfony \ \安全\ \用户\ PasswordAuthenticatedUserInterface核心组件:“汽车”

5.3

password_hashers选项在Symfony 5.3中引入。欧宝娱乐app下载地址在以前的版本中,它被称为编码器

现在Symfony欧宝娱乐app下载地址知道了如何要对密码进行哈希,可以使用UserPasswordHasherInterface服务在将用户保存到数据库之前执行此操作:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ / src /控制器/ RegistrationController.php名称空间应用程序控制器/ /……使用欧宝娱乐app下载地址组件PasswordHasher切肉机UserPasswordHasherInterfaceRegistrationController扩展AbstractController公共函数指数(UserPasswordHasherInterfacepasswordHasher/ /……例如,从注册表单中获取用户数据用户用户(…);plaintextPassword=……;//哈希密码(基于安全。$user类的Yaml配置)hashedPasswordpasswordHasher->hashPassword (用户plaintextPassword);用户->向setPassword (hashedPassword);/ /……}}

提示

:注册表单命令可以帮助您设置注册控制器并添加诸如电子邮件地址验证等功能<一个href="https://github.com/symfonycasts/verify-email-bundle" class="reference external" rel="external noopener noreferrer" target="_blank">欧宝娱乐app下载地址SymfonyCastsVerifyEmailBundle

1 2
Composer需要symfony欧宝娱乐app下载地址casts/verify-email-bundlePHP bin/console make:注册表单

你也可以手动哈希密码通过运行:

1
PHP bin/控制台安全:哈希密码

阅读关于所有可用哈希器和密码迁移的更多信息<一个href="https://www.oldmanjams.com/doc/5.3/security/passwords.html" class="reference internal">密码哈希和验证

防火墙的部分配置/包/ security.yaml大多数重要的部分。“防火墙”是您的身份验证系统:防火墙定义应用程序的哪些部分是安全的如何您的用户将能够验证(例如登录表单,API令牌等)。

  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#配置/包/ security.yaml安全:#……防火墙:戴夫:模式:^ /(_(分析器| wdt) | css |图片| js) /安全:主要:懒惰:真正的供应商:users_in_memory#激活不同的身份验证方式# https://欧宝娱乐app下载地址www.oldmanjams.com/doc/current/security.html firewalls-authentication# https://欧宝娱乐app下载地址www.oldmanjams.com/doc/current/security/impersonating_user.html# switch_user: true

对于每个请求,只有一个防火墙是活动的:Symfony使用欧宝娱乐app下载地址模式键找到第一个匹配(也可以<一个href="https://www.oldmanjams.com/doc/5.3/security/firewall_restriction.html" class="reference internal">由主机或其他东西匹配).

dev防火墙实际上是一个假防火墙:它确保你不会不小心阻止Symfony的开发工具——这些工具存在于像欧宝娱乐app下载地址/ _profiler而且/ _wdt

所有真正的类处理url主要防火墙(不模式键表示匹配所有url)。防火墙可以有多种身份验证模式,换句话说,它支持多种方式来询问“您是谁?”

通常,当用户第一次访问你的网站时,他们是未知的(即没有登录)。如果你现在访问你的主页,你拥有访问权限,您将在工具栏中看到您正在访问防火墙后的页面:

访问防火墙下的URL并不一定要求您进行身份验证(例如,登录表单必须是可访问的,或者应用程序的某些部分是公开的)。中,您将学习如何限制对url、控制器或防火墙内任何其他内容的访问<一个href="https://www.oldmanjams.com/doc/5.3/security.html" class="reference internal">访问控制部分。

提示

懒惰的匿名模式阻止会话在不需要授权(即显式检查用户权限)的情况下启动。这对于保持请求可缓存是很重要的(参见<一个href="https://www.oldmanjams.com/doc/5.3/http_cache.html" class="reference internal">HTTP缓存).

请注意

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

1
开发symfony/profiler-pack欧宝娱乐app下载地址

现在我们了解了防火墙,下一步是为用户创建一种身份验证方法!

表单登录
  • JSON登录
  • HTTP基本
  • 登录链接
  • X.509客户端证书
  • 远程用户
  • 自定义的身份验证器
  • 提示

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

    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    / / src /控制器/ LoginController.php名称空间应用程序控制器使用欧宝娱乐app下载地址FrameworkBundle控制器AbstractController使用欧宝娱乐app下载地址组件HttpFoundation响应使用欧宝娱乐app下载地址组件路由注释路线LoginController扩展AbstractController#[路由('/login',名称:'login')]公共函数指数()响应返回->呈现(“登录/ index.html.twig”, (“controller_name”= >“LoginController”]);}}

    方法启用表单登录验证程序form_login设置:

    • YAML
    • XML
    • PHP
    1 2 3 4 5 6 7 8 9 10 11
    #配置/包/ security.yaml安全:#……防火墙:主要:#……form_login:# "login"是前面创建的路由的名称login_path:登录check_path:登录

    请注意

    login_path而且check_path支持url和路由名(但不能有强制通配符-例如。/登录/ {foo}在哪里喷火没有默认值)。

    启用后,安全系统将未经身份验证的访问者重定向到login_path当他们试图访问一个安全的地方(此行为可以自定义使用<一个href="https://www.oldmanjams.com/doc/5.3/security/access_denied_handler.html" class="reference internal">身份验证入口点).

    编辑登录控制器以呈现登录表单:

    12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22
    / /……+使用Sym欧宝娱乐app下载地址fony\Component\Security\Http\Authentication\AuthenticationUtils;类LoginController扩展AbstractController{#[路由('/login',名称:'login')]—public function index():表示响应+公共函数索引(AuthenticationUtils $ AuthenticationUtils):响应+ //如果有登录错误,获取登录错误+ $error = $authenticationUtils->getLastAuthenticationError();++ //用户最后输入的用户名+ $lastUsername = $authenticationUtils->getLastUsername();+返回$ this - >渲染(“登录/ index . html。嫩枝”,(- 'controller_name' => 'LoginController',+ 'last_username' => $lastUsername,+ 'error' => $error,]);}}

    不要让这个控制器迷惑你。它的工作只是渲染形式:Theform_loginAuthenticator将处理表单提交自动。如果用户提交了无效的电子邮件或密码,验证者将存储错误并重定向回该控制器,在那里我们读取错误(使用AuthenticationUtils),以便显示给使用者。

    最后,创建或更新模板:

    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
    {#模板/登录/ index . html。树枝#}{%扩展“base.html。嫩枝' %}{#……#}{%身体%}{%如果错误%}<div>{{error.messageKey |反式(错误。messagdata, 'security')}}div>{%endif%}<形式行动{{path('login')}}方法“职位”><标签“用户名”>电子邮件:标签><输入类型“文本”id“用户名”的名字“_username”价值{{last_username}}/><标签“密码”>密码:标签><输入类型“密码”id“密码”的名字“_password”/>{#如果你想控制用户成功重定向到的URL  #}<按钮类型“提交”>登录按钮>形式>{%endblock%}

    谨慎

    错误的实例<一个href="https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php" class="reference external" title="AuthenticationException"rel="external noopener noreferrer" target="_blank">AuthenticationException.它可能包含关于身份验证失败的敏感信息。从来没有使用error.message:使用messageKey属性,如示例所示。显示此消息始终是安全的。

    表单可以看起来像任何东西,但它通常遵循一些约定:

    • <形式>元素发送一个帖子登录路由,因为这是你配置的check_pathform_login关键在security.yaml
    • 用户名(或任何用户的“标识符”,如电子邮件)字段有名称_username密码字段有名称_password

    提示

    实际上,所有这些都可以在form_login关键。看到<一个href="https://www.oldmanjams.com/doc/5.3/reference/configuration/security.html" class="reference internal">安全配置参考(SecurityBundle)欲知详情。

    谨慎

    此登录表单目前没有针对CSRF攻击进行保护。读<一个href="https://www.oldmanjams.com/doc/5.3/security.html" class="reference internal">安全关于如何保护您的登录表单。

    就是这样!当您提交表单时,安全系统自动读取_username而且_passwordPOST参数,通过用户提供程序加载用户,检查用户的凭据并对用户进行身份验证或将其发送回可以显示错误的登录表单。

    回顾整个过程:

    1. 用户试图访问受保护的资源(例如。/管理);
    2. 防火墙通过将用户重定向到登录表单(/登录);
    3. /登录页面通过本例中创建的路由和控制器呈现登录表单;
    4. 用户将登录表单提交给/登录
    5. 安全系统(即form_loginAuthenticator)拦截请求,检查用户提交的凭据,验证用户是否正确,如果不正确则将用户发送回登录表单。

    另请参阅

    您可以自定义登录尝试成功或失败时的响应。看到<一个href="https://www.oldmanjams.com/doc/5.3/security/form_login.html" class="reference internal">自定义表单登录验证程序响应

    登录CSRF攻击可以使用在登录表单中添加隐藏CSRF令牌的相同技术来防止。Security组件已经提供了CSRF保护,但是在使用它之前需要配置一些选项。

    首先,你需要在表单登录时启用CSRF:

    • YAML
    • XML
    • PHP
    1 2 3 4 5 6 7 8 9 10
    #配置/包/ security.yaml安全:#……防火墙:secured_area:#……form_login:#……enable_csrf:真正的

    然后,使用csrf_token ()函数在Twig模板中生成一个CSRF令牌,并将其存储为表单的隐藏字段。默认情况下,必须调用HTML字段_csrf_token用于生成该值的字符串必须为进行身份验证

    1 2 3 4 5 6 7 8 9 10
    {/安全/ login.html #模板。树枝#}{#……#}<形式行动{{path('login')}}方法“职位”>{#……登录字段#}<输入类型“隐藏”的名字“_csrf_token”价值{{csrf_token('authenticate')}}><按钮类型“提交”>登录按钮>形式>

    在此之后,您已经保护了登录表单免受CSRF攻击。

    提示

    您可以通过设置更改字段的名称csrf_parameter并通过设置更改令牌IDcsrf_token_id在构型中。看到<一个href="https://www.oldmanjams.com/doc/5.3/reference/configuration/security.html" class="reference internal">安全配置参考(SecurityBundle)欲知详情。

    json_login设置:

    • YAML
    • XML
    • PHP
    1 2 3 4 5 6 7 8 9 10
    #配置/包/ security.yaml安全:#……防火墙:主要:#……json_login:# api_login是我们将在下面创建的路由check_path:api_login

    请注意

    check_path支持url和路由名(但不能有强制通配符-例如。/登录/ {foo}在哪里喷火没有默认值)。

    类请求时,验证程序运行check_path.首先,为这个路径创建一个控制器:

    1 2 3
    src/ controller /ApiLoginController.php bin/console make:controller——no-template ApiLoginController.php
    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
    / / src /控制器/ ApiLoginController.php名称空间应用程序控制器使用欧宝娱乐app下载地址FrameworkBundle控制器AbstractController使用欧宝娱乐app下载地址组件HttpFoundation响应使用欧宝娱乐app下载地址组件路由注释路线ApiLoginController扩展AbstractController#[Route('/api/login', name: 'api_login')]公共函数指数()响应返回->json ([“消息”= >“欢迎使用你的新控制器!”“路径”= >“src /控制器/ ApiLoginController.php”]);}}

    在验证程序成功验证用户后,将调用此登录控制器。你可以获得认证的用户,生成一个令牌(或任何你需要返回的东西),并返回JSON响应:

    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
    / /……+使用App\实体\用户;+使用Sym欧宝娱乐app下载地址fony\Component\Security\Http\Attribute\CurrentUser;类ApiLoginController扩展AbstractController{#[路由('/api/login',名称:'api_login')]—public function index():表示响应+公共函数索引(#[CurrentUser] ?User $ User):响应+ if (null === $user) {+返回$this->json([+ 'message' => '缺少凭据',+], Response::HTTP_UNAUTHORIZED);+}++ $token =…//为$user创建一个API令牌+返回json ([$ this - >- 'message' => '欢迎来到您的新控制器!”,- 'path' => 'src/Controller/ApiLoginController.php',+ 'user' => $user->getUserIdentifier(),+ 'token' => $token,]);}}

    请注意

    # (CurrentUser)只能在控制器参数中使用,以检索已验证的用户。在服务中,您将使用<一个href="https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/Core/Security.php" class="reference external" title="getUser ()"rel="external noopener noreferrer" target="_blank">getUser ()

    就是这样!总结一下这个过程:

    1. 客户端(例如前端)做出一个POST请求内容类型:application / json头来/ api /登录用户名(即使你的标识符实际上是一个电子邮件)和密码密钥:

      1 2 3 4
      “用户名”“dunglas@example.com”“密码”“我的密码”
    2. 安全系统拦截请求,检查用户提交的凭据并验证用户身份。如果凭证不正确,将返回一个HTTP 401 Unauthorized JSON响应,否则您的控制器将运行;
    3. 你的控制器创建了正确的响应:

      1 2 3 4
      “用户”“dunglas@example.com”“令牌”“45 be42……”

    提示

    JSON请求格式可以在json_login关键。看到<一个href="https://www.oldmanjams.com/doc/5.3/reference/configuration/security.html" class="reference internal">安全配置参考(SecurityBundle)欲知详情。

    HTTP基本认证是一个标准化的HTTP认证框架。它使用浏览器中的对话框询问凭据(用户名和密码),Symfony的HTTP基本身份验证器将验证这些凭据。欧宝娱乐app下载地址

    添加http_basic打开防火墙以启用HTTP基本身份验证:

    • YAML
    • XML
    • PHP
    1 2 3 4 5 6 7 8 9
    #配置/包/ security.yaml安全:#……防火墙:主要:#……http_basic:域:担保区域

    就是这样!每当未经身份验证的用户试图访问受保护的页面时,Symfony将通知浏览器它需要启动HTTP基本身份验证(使用欧宝娱乐app下载地址WWW-Authenticate响应头)。然后,验证方验证凭证并验证用户。

    请注意

    你不能使用<一个href="https://www.oldmanjams.com/doc/5.3/security.html" class="reference internal">注销使用HTTP基本验证器。即使您从Symfony注销,您的浏览器也会“记住”欧宝娱乐app下载地址您的凭据,并在每次请求时发送它们。