具有安全和数据库用户的Symfony 4登录表单

Dim*_*s K 2 login symfony4

大约一个星期前,我对Symfony完全陌生,我认为我应该只是沉浸在Symfony 4中。经过一周尝试解决基本登录问题后,我相信文档仍然缺少一些内容。

现在,我找到了一个解决方案,并将与您可能在做错事情的一些技巧一起分享。答案的第一部分是建议列表,第二部分是使用从头开始进行有效登录的项目的创建(假设您已经安装了作曲器,并使用了apache之类的服务器)。

Dim*_*s K 8

第1部分:建议

403禁止

检查access_control:security.yaml中的密钥。规则的顺序会产生影响,因为每次最多只能匹配一个规则。将最具体的规则放在首位。

login_check

确保表单操作将您引导至login_check路径,或将其更改为security.yaml中的任何内容

还要检查是否已login_check在控制器或routes.yaml中声明了该路径的路由。

输入名称

Symfony表单倾向于将输入名称封装在数组中,而只希望输入名称被命名,_username并且_password(可以在security.yaml中进行更改)将其计为登录尝试。因此,请检查输入以确保名称属性正确。

第2部分:完整的Symfony 4登录

项目设置

让我们从创建项目开始。打开cmd / terminal,然后转到要包含项目文件夹的文件夹。

cd .../MyProjects
composer create-project symfony/website-skeleton my-project
cd my-project
Run Code Online (Sandbox Code Playgroud)

现在,您已经在... / MyProjects / my-project中创建了一个Symfony 4网站模板,cmd / terminal位于该路径中,并将正确执行其余命令。

在您的... / MyProjects / my-project / public文件夹中检查.htaccess文件。如果存在,则可以,请运行以下命令。

composer require symfony/apache-pack
Run Code Online (Sandbox Code Playgroud)

您现在可以通过访问my-project.dev/public找到您的站点。如果要删除此公共路径,则应使用.htaccess文件,而不要移动index.php

项目设定

1)编辑.env文件中的DATABASE_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 }
Run Code Online (Sandbox Code Playgroud)

一些解释:

App\Entity\User 是您将在一段时间内创建的用于处理登录的用户实体。

user供应商仅需要在供应商和防火墙相匹配的名称。

logout,如果你想允许用户...好,退出键必须申报。

中的值#comment显示了我们稍后将使用的默认值,并作为您更可能更改的内容的参考。

用户实体

用户必须具有角色,但可以具有更多角色。因此,让我们UserRole首先为ManyToMany关系建立一个实体。

php bin/console make:entity userRole
Run Code Online (Sandbox Code Playgroud)

所有实体均以id属性开头。也添加一个role

php bin/console make:entity user
Run Code Online (Sandbox Code Playgroud)

用户需求usernamepasswordroles性能,但您可以添加更多。

让我们编辑src / Entity / User.php文件:

UserInterface接口添加到您的User班级。

use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
Run Code Online (Sandbox Code Playgroud)

编辑generate getRoles(),使其返回字符串数组。

public function getRoles(): array
{
    $roles = $this->roles->toArray();
    foreach($roles as $k => $v) {
        $roles[$k] = $v->getRole();
    }
    return $roles;
}
Run Code Online (Sandbox Code Playgroud)

getSalt()eraseCredentials()一些函数来实现UserInterface接口。

public function getSalt()
{
    return null;
}
public function eraseCredentials()
{
}
Run Code Online (Sandbox Code Playgroud)

使用bcrypt算法(如我们在security.yaml中设置的那样),我们不需要盐。它会自动生成一个。不,您不会在任何地方存储此盐,是的,每次相同的密码都会产生不同的哈希值。但是,是的,它将以某种方式起作用(魔术...)。

如果需要使用盐的其他算法,则需要saltUser实体上添加一个属性。

主页

为了进行测试,我们将创建一个主页

php bin/console make:controller homepage
Run Code Online (Sandbox Code Playgroud)

编辑生成的src / Controller / HomepageController.php文件,将根更改为/

@Route("/", name="homepage")
Run Code Online (Sandbox Code Playgroud)

登录控制器

php bin/console make:controller login
Run Code Online (Sandbox Code Playgroud)

编辑生成的src / Controller / LoginController.php文件,使其如下所示:

<?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() {}
}
Run Code Online (Sandbox Code Playgroud)

登录表格

php bin/console make:form login
Run Code Online (Sandbox Code Playgroud)

您不必将其与User实体关联。

编辑生成的src / Form / LoginType.php文件以添加以下内容:

use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
Run Code Online (Sandbox Code Playgroud)

替换为:

$builder
    ->add('_username')
    ->add('_password', PasswordType::class)
    ->add('login', SubmitType::class, ['label' => 'Login'])
;
Run Code Online (Sandbox Code Playgroud)

并添加此功能,以防止Symfony通过将它们括在其中来更改您在上面请求的输入名称 login[...]

public function getBlockPrefix() {}
Run Code Online (Sandbox Code Playgroud)

登录模板

编辑template / 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) }}
Run Code Online (Sandbox Code Playgroud)

数据库生成

php bin/console doctrine:migrations:generate
php bin/console doctrine:migrations:migrate
Run Code Online (Sandbox Code Playgroud)

根据UserUserRole实体,这应该已经生成了数据库。

产生密码

以下命令将为您提供可以直接插入数据库的哈希密码。密码将使用security.yaml中指定的算法进行哈希处理。

php bin/console security:encode-password my-password
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!