大约一周前,我在Symfony上是一个总菜鸟,我想我应该潜入Symfony 4.经过一周的尝试解决基本的登录问题,我相信文档仍然缺少某些部分。
现在我找到了一个解决方案,我将分享一些关于你可能做错的提示。答案的第一部分是建议列表,第二部分是创建一个从头开始工作的项目(假设您已经安装了composer并使用像apache这样的服务器)。
答案 0 :(得分:5)
403禁止
检查security.yaml中的access_control:
键。规则的顺序会产生影响,因为每次只能匹配一条规则。保留最具体的规则。
<强> login_check 强>
确保表单操作将您转到login_check
路径,或者您在 security.yaml 中将其更改为的任何路径。
同时检查您是否已在控制器或 routes.yaml 中为login_check
路径声明了路径。
输入名称
Symfony表单倾向于将输入名称封装在数组中,而它只希望将它们命名为_username
和_password
(您可以在 security.yaml 中更改它)将其视为登录尝试。因此,检查输入以确保名称属性正确。
让我们从创建项目开始。打开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
用户需要username
,password
和roles
属性,但您可以添加更多内容。
让我们编辑 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
根据您的User
和UserRole
实体,这应该已经生成了您的数据库。
以下命令将为您提供可以直接插入数据库的散列密码。密码将使用 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 }