具有安全性和数据库用户的Symfony 4登录表单 [英] Symfony 4 login form with security and database users
问题描述
大约一周前,我对Symfony完全陌生,我认为我应该只学习Symfony4.经过一周的尝试解决基本登录问题后,我相信文档仍然缺少某些部分.
I was a total noob on Symfony about a week ago and I thought I should just dive in Symfony 4. After a week of trying to solve the basic login problem, I believe the documentation is still missing some parts.
现在,我找到了一个解决方案,并将与您可能在做错事情的一些技巧一起分享.答案的第一部分是建议列表,第二部分是使用从头开始进行有效登录的项目的创建(假设您已经安装了作曲器并使用了apache之类的服务器).
Now I've found a solution and I will share it along with some tips on what you might be doing wrong. First part of the answer is a list of suggestions, while the second part is the creation of a project with working login from scratch (supposing you already have composer installed and using a server like apache).
推荐答案
第1部分:建议
403禁止访问
检查security.yaml中的access_control:
密钥.规则的顺序会产生影响,因为每次最多只能匹配一个规则.将最具体的规则放在首位.
Check the access_control:
key in security.yaml. The order of the rules has impact, since no more than one rule will match each time. Keep most specific rules on top.
login_check
确保表单操作将您引导至login_check
路径,或者将其更改为 security.yaml 中的任何内容.
Make sure the form action sends you to the login_check
path, or whatever you changed it to in security.yaml.
还要检查是否已在控制器或 routes.yaml 中声明了login_check
路径的路由.
Also check that you have declared a route for the login_check
path either in a controller or in routes.yaml.
输入名称
Symfony形式倾向于将输入名称封装在数组中,而只希望它们被命名为_username
和_password
(您可以在 security.yaml 中进行更改)以将其计为登录尝试.因此,请检查输入内容以确保名称属性正确.
Symfony forms tend to encapsulate input names in an array, while it only expects them to be named _username
and _password
(you can change that in security.yaml) to count it as a login attempt. So inspect the inputs to make sure the name attributes are correct.
让我们从创建项目开始.打开cmd/terminal,然后转到要包含项目文件夹的文件夹.
Let's start by creating the project. Open cmd/terminal and go to the folder you want to contain the project folder.
cd .../MyProjects
composer create-project symfony/website-skeleton my-project
cd my-project
现在,您已经在 .../MyProjects/my-project 中创建了Symfony 4网站模板,cmd/terminal位于该路径中,并将正确执行其余命令.
Now you have created a Symfony 4 website template in .../MyProjects/my-project and the cmd/terminal is in that path and will execute the rest of the commands properly.
在您的 .../MyProjects/my-project/public 文件夹中检查.htaccess文件.如果存在,则可以,请运行以下命令.
Check in your .../MyProjects/my-project/public folder for a .htaccess file. If it exists you are fine, else run the following command.
composer require symfony/apache-pack
您现在可以通过访问 my-project.dev/public 来找到您的站点.如果要删除此公共路径,则应使用 .htaccess 文件,而不要移动 index.php .
You can now find your site by visiting my-project.dev/public. If you want to remove this public path, you should do so using the .htaccess file, not moving the index.php.
1)编辑 .env 文件中的DATABASE_URL
键,使其与您的数据库设置相对应.
1) Edit the DATABASE_URL
key inside the .env file to correspond to your database settings.
2)编辑 config/packages/security.yaml 文件,如下所示:
2) Edit the config/packages/security.yaml file, so it looks like this:
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 }
一些解释:
App\Entity\User
是您将在一段时间内创建的用于处理登录的用户实体.
App\Entity\User
is the User entity you 'll create in a while to handle the login.
user
提供程序只是一个名称,需要在提供程序和防火墙中匹配.
The user
provider is just a name that needs to have a match in providers and firewalls.
如果要允许用户...退出,必须声明logout
键.
The logout
key must be declared if you want to allow the user to... well, logout.
#comment
中的值显示了我们稍后将使用的默认值,并作为您更可能更改的内容的参考.
Values in #comment
reveal the default value we'll be using later on and act as a reference of what you are more likely to change.
用户必须具有角色,但可以具有更多角色.因此,让我们首先为ManyToMany关系建立一个UserRole
实体.
A user must have a role, but could have more. So let's build a UserRole
Entity first for a ManyToMany relationship.
php bin/console make:entity userRole
所有实体均以id属性开头.还要添加一个role
.
All entities start with an id property. Add a role
too.
php bin/console make:entity user
用户需要username
,password
和roles
属性,但是您可以添加更多内容.
User needs the username
, password
and roles
properties, but you can add more.
让我们编辑 src/Entity/User.php 文件:
将UserInterface
接口添加到您的User
类中.
Add the UserInterface
interface to your User
class.
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
编辑生成的getRoles()
,以使其返回字符串数组.
Edit the generated getRoles()
, to make it return string array.
public function getRoles(): array
{
$roles = $this->roles->toArray();
foreach($roles as $k => $v) {
$roles[$k] = $v->getRole();
}
return $roles;
}
getSalt()
和eraseCredentials()
是用于实现UserInterface
接口的功能.
getSalt()
and eraseCredentials()
are functions to implement the UserInterface
interface.
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
使用bcrypt
算法(如我们在 security.yaml 中设置的),我们不需要加盐.它会自动生成一个.不,您不会在任何地方存储此盐,是的,每次相同的密码都会产生不同的哈希值.但是,是的,它将以某种方式起作用(魔术...).
Using the bcrypt
algorithm (as we set in security.yaml) we don't need a salt. It generates automatically one. No, you don't store this salt anywhere and yes, it will produce different hash for the same password every time. But yes, it will work somehow (magic...).
如果需要使用盐的其他算法,则需要在User
实体上添加salt
属性.
If you need a different algorithm, that uses salt, you need to add a salt
property on the User
entity.
出于测试目的,我们将创建一个主页
For testing purposes we will create a homepage
php bin/console make:controller homepage
编辑生成的 src/Controller/HomepageController.php 文件,将根目录更改为/
Edit the generated src/Controller/HomepageController.php file to change the root to /
@Route("/", name="homepage")
登录控制器
php bin/console make:controller login
编辑生成的 src/Controller/LoginController.php 文件,使其如下所示:
Edit the generated src/Controller/LoginController.php file to make it like this:
<?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() {}
}
登录表格
php bin/console make:form login
您不必将其关联到User
实体.
You don't have to associate it to the User
entity.
编辑生成的 src/Form/LoginType.php 文件以添加此文件:
Edit the generated src/Form/LoginType.php file to add this:
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[...]
and add this function, to prevent Symfony from changing the input names you requested above by enclosing them in login[...]
public function getBlockPrefix() {}
登录模板
编辑 templates/login/index.html.twig 文件,以将该代码添加到{% block body %} ... {% endblock %}
:
Login Template
Edit the templates/login/index.html.twig file to add this code in the {% 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) }}
数据库生成
php bin/console doctrine:migrations:generate
php bin/console doctrine:migrations:migrate
这应该已经根据您的User
和UserRole
实体生成了数据库.
This should have generated your database, according to your User
and UserRole
entities.
以下命令将为您提供可以直接插入数据库的哈希密码.密码将使用 security.yaml 中指定的算法进行哈希处理.
The following command will provide you with a hashed password you can directly insert into the database. The password will be hashed with the algorithm specified in security.yaml.
php bin/console security:encode-password my-password
希望这会有所帮助!
这篇关于具有安全性和数据库用户的Symfony 4登录表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!