Login 具有安全和数据库用户的Symfony 4登录表单
大约一周前,我在Symfony上是个彻头彻尾的傻瓜,我想我应该在Symfony 4上潜水。在尝试解决基本登录问题一周后,我相信文档仍然缺少一些部分 现在,我找到了一个解决方案,我将与大家分享它,以及一些关于你可能做错了什么的提示。答案的第一部分是建议列表,而第二部分是使用从头开始的工作登录创建项目(假设您已经安装了composer并使用apache之类的服务器)。第1部分:建议 403禁止 检查Login 具有安全和数据库用户的Symfony 4登录表单,login,symfony4,Login,Symfony4,大约一周前,我在Symfony上是个彻头彻尾的傻瓜,我想我应该在Symfony 4上潜水。在尝试解决基本登录问题一周后,我相信文档仍然缺少一些部分 现在,我找到了一个解决方案,我将与大家分享它,以及一些关于你可能做错了什么的提示。答案的第一部分是建议列表,而第二部分是使用从头开始的工作登录创建项目(假设您已经安装了composer并使用apache之类的服务器)。第1部分:建议 403禁止 检查访问控制:输入security.yaml。规则的顺序会产生影响,因为每次匹配的规则不会超过一个。把最具
访问控制:
输入security.yaml。规则的顺序会产生影响,因为每次匹配的规则不会超过一个。把最具体的规则放在首位
登录检查
确保表单操作将您发送到login\u check
路径,或您在security.yaml中将其更改为的任何路径
还要检查您是否已在控制器或routes.yaml中为登录检查
路径声明了路由
输入名称
Symfony表单倾向于将输入名称封装在一个数组中,而它只希望它们被命名为\u username
和\u password
(您可以在security.yaml中更改它们)以将其计为登录尝试。因此,检查输入以确保名称属性正确
第2部分:完整Symfony 4登录
项目设置
让我们从创建项目开始。打开cmd/terminal并转到要包含项目文件夹的文件夹
cd .../MyProjects
composer create-project symfony/website-skeleton my-project
cd my-project
现在您已经在…/MyProjects/myproject中创建了一个symfony4网站模板,cmd/terminal位于该路径中,将正确执行其余命令
签入…/MyProjects/myproject/public文件夹以获取.htaccess文件。如果它存在,您就可以了,否则运行以下命令
composer require symfony/apache-pack
您现在可以通过访问my-project.dev/public找到您的站点。如果要删除此公共路径,应使用.htaccess文件,而不是移动index.php
项目设置
1) 编辑.env文件中的DATABASE\u URL
键,使其与数据库设置相对应
2) 编辑config/packages/security.yaml文件,使其如下所示:
security:
encoders:
App\Entity\User:
algorithm: bcrypt
providers:
user:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
provider: user
form_login:
#login_path: login
#check_path: login_check
default_target_path: homepage
#username_parameter: _username
#password_parameter: _password
logout:
#path: /logout
#target: /
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
- { path: ^/admin, roles: ROLE_ADMIN }
<?php
namespace App\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use App\Form\LoginType;
class LoginController extends Controller
{
/**
* @Route("/login", name="login")
*/
public function index(AuthenticationUtils $authenticationUtils)
{
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(LoginType::class);
return $this->render('login/index.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
'form' => $form->createView(),
]);
}
/**
* @Route("/logout", name="logout")
*/
public function logout() {}
/**
* @Route("/login_check", name="login_check")
*/
public function login_check() {}
}
一些解释:
App\Entity\User
是您将在一段时间内创建的用于处理登录的用户实体
用户
提供程序只是一个名称,需要在提供程序和防火墙中进行匹配
如果要允许用户执行以下操作,则必须声明注销
键。。。嗯,注销
#comment
中的值显示了我们稍后将使用的默认值,并作为您更可能更改的内容的参考
用户实体
用户必须具有角色,但可以具有更多角色。因此,让我们首先为多人关系构建一个UserRole
实体
php bin/console make:entity userRole
所有实体都以id属性开头。也添加一个角色
php bin/console make:entity user
用户需要用户名
、密码
和角色
属性,但您可以添加更多
让我们编辑src/Entity/User.php文件:
将UserInterface
界面添加到User
类中
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
编辑生成的getRoles()
,使其返回字符串数组
public function getRoles(): array
{
$roles = $this->roles->toArray();
foreach($roles as $k => $v) {
$roles[$k] = $v->getRole();
}
return $roles;
}
getSalt()
和eraseCredentials()
是实现UserInterface
接口的函数
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
使用bcrypt
算法(正如我们在security.yaml中设置的那样),我们不需要盐。它会自动生成一个。不,您不会将此盐存储在任何位置,而且是的,它每次都会为同一密码生成不同的哈希值。但是是的,它会以某种方式起作用(魔法…)
如果需要使用salt的不同算法,则需要在User
实体上添加salt
属性
主页
出于测试目的,我们将创建一个主页
php bin/console make:controller homepage
编辑生成的src/Controller/HomepageController.php文件,将根目录更改为/
登录控制器
编辑生成的src/Controller/LoginController.php文件,使其如下所示:
security:
encoders:
App\Entity\User:
algorithm: bcrypt
providers:
user:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
provider: user
form_login:
#login_path: login
#check_path: login_check
default_target_path: homepage
#username_parameter: _username
#password_parameter: _password
logout:
#path: /logout
#target: /
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
- { path: ^/admin, roles: ROLE_ADMIN }
<?php
namespace App\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use App\Form\LoginType;
class LoginController extends Controller
{
/**
* @Route("/login", name="login")
*/
public function index(AuthenticationUtils $authenticationUtils)
{
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(LoginType::class);
return $this->render('login/index.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
'form' => $form->createView(),
]);
}
/**
* @Route("/logout", name="logout")
*/
public function logout() {}
/**
* @Route("/login_check", name="login_check")
*/
public function login_check() {}
}
您不必将其与用户
实体关联
编辑生成的src/Form/LoginType.php文件以添加以下内容:
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
替换此项:
$builder
->add('_username')
->add('_password', PasswordType::class)
->add('login', SubmitType::class, ['label' => 'Login'])
;
并添加此功能,以防止Symfony通过将您请求的输入名称包含在login[…]
public function getBlockPrefix() {}
登录模板
编辑templates/login/index.html.twig文件,将此代码添加到{%block body%}。。。{%endblock%}
:
{% if error %}
<div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
{{ form_start(form, {'action': path('login_check'), 'method': 'POST'}) }}
{{ form_widget(form) }}
{{ form_end(form) }}
这应该已经根据您的用户
和用户角色
实体生成了您的数据库
生成密码
以下命令将为您提供一个哈希密码,您可以直接将其插入数据库。密码将使用security.yaml中指定的算法进行散列
希望这有帮助 非常感谢,文档中缺少一些重要的东西,但效果非常好。对于其他人,请检查访问控制条目的顺序,因为一个放错位置的条目可能会阻塞整个过程
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
这是可行的,但这不是
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
php bin/console security:encode-password my-password
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }