Symfony 4登录表单,包含安全和数据库用户

时间:2018-04-29 01:50:53

标签: login symfony4

大约一周前,我在Symfony上是一个总菜鸟,我想我应该潜入Symfony 4.经过一周的尝试解决基本的登录问题,我相信文档仍然缺少某些部分。

现在我找到了一个解决方案,我将分享一些关于你可能做错的提示。答案的第一部分是建议列表,第二部分是创建一个从头开始工作的项目(假设您已经安装了composer并使用像apache这样的服务器)。

2 个答案:

答案 0 :(得分:5)

第1部分:建议

403禁止

检查security.yaml中的access_control:键。规则的顺序会产生影响,因为每次只能匹配一条规则。保留最具体的规则。

<强> login_check

确保表单操作将您转到login_check路径,或者您在 security.yaml 中将其更改为的任何路径。

同时检查您是否已在控制器或 routes.yaml 中为login_check路径声明了路径。

输入名称

Symfony表单倾向于将输入名称封装在数组中,而它只希望将它们命名为_username_password(您可以在 security.yaml 中更改它)将其视为登录尝试。因此,检查输入以确保名称属性正确。

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

项目设置

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

cd .../MyProjects
composer create-project symfony/website-skeleton my-project
cd my-project

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

检入 ... / MyProjects / my-project / public 文件夹中的.htaccess文件。如果它存在你没事,否则运行以下命令。

composer require symfony/apache-pack

您现在可以访问 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 }

一些解释:

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

user提供商只是一个需要在提供商和防火墙中匹配的名称。

如果您想允许用户......好好注销,则必须声明logout密钥。

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

用户实体

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

php bin/console make:entity userRole

所有实体都以id属性开头。也添加role

php bin/console make:entity user

用户需要usernamepasswordroles属性,但您可以添加更多内容。

让我们编辑 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的其他算法,则需要在salt实体上添加User属性。

主页

出于测试目的,我们将创建一个主页

php bin/console make:controller homepage

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

@Route("/", name="homepage")

登录控制器

php bin/console make:controller login

编辑生成的 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() {}
}

登录表

php bin/console make:form login

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

编辑生成的 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) }}

数据库生成

php bin/console doctrine:migrations:generate
php bin/console doctrine:migrations:migrate

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

生成密码

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

php bin/console security:encode-password my-password

希望这有帮助!

答案 1 :(得分:0)

非常感谢,文档缺少一些重要的东西,但这非常有用。对于其他人,请检查访问控制条目的顺序,因为一个放错位置的条目可能会阻止整个过程。

    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 }