本文概述
- 1.创建登录路径
- 2.创建登录表单身份验证器
- 3.注册Guard Authenticator
- 4.创建登录视图
- 5.访问和登录
- 6.创建注销路径
- 7.启用注销
Symfony 4非常容易实现, 我们将在短期内向你说明如何创建登录和注销路径:
1.创建登录路径 【如何在Symfony 4.3中实现自己的用户身份验证系统(第3部分(创建登录表单和注销路径))】最初, 我们需要创建一条路径, 用户可以在其中访问登录表单。在应用程序的控制器目录(/ src / Controller /)中创建具有以下内容的SecurityController.php文件:
<
?php// src/Controller/SecurityController.phpnamespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController{/*** @Route("/login", name="app_login")*/public function login(AuthenticationUtils $authenticationUtils): Response{// Get the login error if there is one$error = $authenticationUtils->
getLastAuthenticationError();
// Retrive the last email entered by the user$lastUsername = $authenticationUtils->
getLastUsername();
return $this->
render('security/login.html.twig', ['last_username' =>
$lastUsername, 'error' =>
$error]);
}}
通过依赖项注入, AuthenticationUtils实例将通过登录对象作为第一个参数接收该对象, 你可以从该对象中获取示例信息, 最后的身份验证错误以及表单上提供的用户名。
2.创建登录表单身份验证器 接下来, 你将需要创建扩展了AbstractFormLoginAuthenticator基类的authenticator类, 这将使表单登录身份验证更加容易。此类将在构造函数中接收此模块所需的4个关键组件, 即实体管理器(用于创建查询), 路由器接口(用于创建路由), CSRF令牌管理器(检查表单是否有效)和密码编码器(以检查身份验证是否有效)。
当supports方法返回true时, 将执行此身份验证器(在步骤3中注册后)。在这种情况下, 当当前路由为app_login且方法为POST(提交表单时)时, 它将被触发:
<
?php// src/Security/LoginFormAuthenticator.phpnamespace App\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator{use TargetPathTrait;
private $entityManager;
private $router;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(EntityManagerInterface $entityManager, RouterInterface $router, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder){$this->
entityManager = $entityManager;
$this->
router = $router;
$this->
csrfTokenManager = $csrfTokenManager;
$this->
passwordEncoder = $passwordEncoder;
}public function supports(Request $request){return 'app_login' === $request->
attributes->
get('_route')&
&
$request->
isMethod('POST');
}public function getCredentials(Request $request){$credentials = ['email' =>
$request->
request->
get('email'), 'password' =>
$request->
request->
get('password'), 'csrf_token' =>
$request->
request->
get('_csrf_token'), ];
$request->
getSession()->
set(Security::LAST_USERNAME, $credentials['email']);
return $credentials;
}public function getUser($credentials, UserProviderInterface $userProvider){$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->
csrfTokenManager->
isTokenValid($token)) {throw new InvalidCsrfTokenException();
}$user = $this->
entityManager->
getRepository(User::class)->
findOneBy(['email' =>
$credentials['email']]);
if (!$user) {// fail authentication with a custom errorthrow new CustomUserMessageAuthenticationException('Email could not be found.');
}return $user;
}public function checkCredentials($credentials, UserInterface $user){return $this->
passwordEncoder->
isPasswordValid($user, $credentials['password']);
}public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey){if ($targetPath = $this->
getTargetPath($request->
getSession(), $providerKey)) {return new RedirectResponse($targetPath);
}// For example : return new RedirectResponse($this->
router->
generate('some_route'));
throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
}protected function getLoginUrl(){return $this->
router->
generate('app_login');
}}
请注意, 你需要在此类中处理, 特别是在onAuthenticationSuccess回调上, 现在用户会发生什么。通常, 你应该将他重定向到应用程序的索引页面或其他内容, 因此请确保根据你的需要修改回调的代码, 例如, 不要引发异常, 而只需重定向到我们的索引路由即可:
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey){if ($targetPath = $this->
getTargetPath($request->
getSession(), $providerKey)) {return new RedirectResponse($targetPath);
}//Redirect user to homepagereturn new RedirectResponse($this->
router->
generate('app_index'));
}
3.注册Guard Authenticator 身份验证器已经存在, 但是你需要在主防火墙中注册它:
# app/config/packages/security.yamlsecurity:firewalls:main:anonymous: trueguard:authenticators:- App\Security\LoginFormAuthenticator# Easy way to control access for large sections of your site# Note: Only the *first* access control that matches will be usedaccess_control:- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
这样做, 该类将被注册, 并在该类的supports方法返回true时作出反应。
4.创建登录视图 最后但同样重要的是, 在登录路径中, 我们呈现了一个Twig视图, 即login.html.twig, 尚未创建, 并将包含以下标记(存储在/ app / templates / security /中):
{# /app/templates/security/login.html.twig #}{% extends 'base.html.twig' %}{% block title %}Log in!{% endblock %}{% block body %}<
form method="post">
{# If there's any error, display it to the user #}{% if error %}<
div class="alert alert-danger">
{{ error.messageKey|trans(error.messageData, 'security') }}<
/div>
{% endif %}<
h1>
Please sign in<
/h1>
{# Email Input #}<
label for="inputEmail" class="sr-only">
Email<
/label>
<
input type="email" value="http://www.srcmini.com/{{ last_username }}" name="email" id="inputEmail" class="form-control" placeholder="Email" required autofocus>
{# Password Input #}<
label for="inputPassword" class="sr-only">
Password<
/label>
<
input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
{# CSRF Token Input #}<
input type="hidden" name="_csrf_token" value="http://www.srcmini.com/{{ csrf_token('authenticate') }}" />
<
button class="btn btn-lg btn-primary" type="submit">
Sign in<
/button>
<
/form>
{% endblock %}
5.访问和登录 创建视图后, 如果你尝试访问路线mywebsite.com/login, 则会看到登录表单:
文章图片
提供通过本文第2部分中创建的注册表单注册的用户的一些凭据。如果你在其中指定了重定向路由, 则所有操作都会正常进行, 并且你将被重定向到该路由, 并且你会在开发工具中看到已通过身份验证的信息:
这就是登录部分!
6.创建注销路径 现在, 你的用户如果登录也应该能够关闭会话, 因此你需要公开注销路径。你可以在还创建了登录路由的同一SecurityController中创建它, 因此可以添加它, 这是一个简单的空操作, 名为logout:
<
?php// src/Controller/SecurityController.phpnamespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController{/*** @Route("/logout", name="app_logout")*/public function logout(): Response{// controller can be blank: it will never be executed!}}
请注意, 该路由将具有在下一步中使用的标识符, 以启用身份验证系统的注销功能。
7.启用注销 现在已经存在注销路由, 你需要在security.yaml文件的主防火墙中指定它:
# app/config/packages/security.yamlsecurity:firewalls:main:logout:path: app_logout# where to redirect after logout ?? You can specify the target property# target: app_any_route
你还可以在此块中指定注销后将用户重定向到的位置。注册此路由后, 登录后访问路由mywebsite.com/logout, 该会话将被删除, 用户将需要再次登录该应用程序。
阅读教程的所有部分” 如何在SYMFONY 4.3中实施你自己的用户认证系统”
- 第1部分:创建自定义用户类。
- 第2部分:创建用户注册表单。
- 第3部分:创建登录表单和注销路径。
- https://symfony.com/doc/current/security.html
推荐阅读
- 如何在Symfony 4.3中实现自己的用户身份验证系统(第2部分(创建用户注册表单))
- Linux-HA 高可用开源方案 Keepalived VS Heartbeat 的选择
- hpwm.h头文件和hpwm.c文件,分别复制,保存成hpwm.h文件和hpwm.c文件,就能使用
- 实例4,循迹模块的使用和循迹小车的实现
- MYSQL中group_concat有长度限制!默认1024
- RHEL 6.3 as 64bit 配置yum源
- 实物2操作(stc8a8k按键使用)
- 安装MYSQL错误“conflicts with file from package mysql-libs-*” 解决方法
- Linux中找不到service命令