Tôi có một hệ thống Symfony 3.3.13 với nhiều hình thức khác nhau.tùy chọn xác thực của khách hàng + form_login ngắt tất cả mã thông báo csrf
Để đạt được "liên kết sâu" trong các biểu mẫu này, ví dụ: việc có thể bấm vào một liên kết email, đăng nhập và sau đó được chuyển hướng đến các hình thức Tôi đã thêm các thay đổi sau:
config.yml
framework:
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
...
more
...
security.yml
security:
providers:
zog:
id: app.zog_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
logout:
path: /logout
target:/
guard:
authenticators:
- app.legacy_token_authenticator
- app.token_authenticator
entry_point: app.legacy_token_authenticator
form_login: <--this line alone breaks CSRF
use_referer: true <--I tried partial combinations, none seems to make CSRF work
login_path: /security/login
use_forward: true
success_handler: login_handler
csrf_token_generator: security.csrf.token_manager <--added based on answer, doesn't help
src/AppBundle/Resources/config/services.yml
login_handler:
class: AppBundle\Service\LoginHandler
arguments: ['@router', '@doctrine.orm.entity_manager', '@service_container']
src/AppBundle/Service/Loginhandler.php
<?php
/**
* Created by PhpStorm.
* User: jochen
* Date: 11/12/17
* Time: 12:31 PM
*/
namespace AppBundle\Service;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Routing\RouterInterface;
use Doctrine\ORM\EntityManager;
class LoginHandler implements AuthenticationSuccessHandlerInterface
{
private $router;
private $container;
private static $key;
public function __construct(RouterInterface $router, EntityManager $em, $container) {
self::$key = '_security.main.target_path';
$this->router = $router;
$this->em = $em;
$this->session = $container->get('session');
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token) {
//check if the referer session key has been set
if ($this->session->has(self::$key)) {
//set the url based on the link they were trying to access before being authenticated
$route = $this->session->get(self::$key);
//remove the session key
$this->session->remove(self::$key);
//if the referer key was never set, redirect to a default route
return new RedirectResponse($route);
} else{
$url = $this->generateUrl('portal_job_index');
return new RedirectResponse($url);
}
}
}
tôi cũng đã thực hiện chắc chắn rằng CSRF được kích hoạt trên biểu mẫu đăng nhập như thế này:
src/AppBundle/nguồn/views/security/login.html.twig
<form action="{{ path('app_security_login') }}" method="post" autocomplete="off">
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
ứng dụng /config/services.yml
app.legacy_token_authenticator:
class: AppBundle\Security\LegacyTokenAuthenticator
arguments: ["@router", "@session", "%kernel.environment%", "@security.csrf.token_manager"]
src/AppBundle/Security \ legacyTokenAuthenticator
class LegacyTokenAuthenticator extends AbstractGuardAuthenticator
{
private $session;
private $router;
private $csrfTokenManager;
public function __construct(
RouterInterface $router,
SessionInterface $session,
$environment,
CsrfTokenManagerInterface $csrfTokenManager
) {
if ($environment != 'test'){
session_start();
}
$session->start();
$this->setSession($session);
$this->csrfTokenManager = $csrfTokenManager;
$this->router = $router;
}
/**
* @return mixed
*/
public function getSession()
{
return $this->session;
}
/**
* @param mixed $session
*/
public function setSession($session)
{
$this->session = $session;
}
/**
* Called on every request. Return whatever credentials you want,
* or null to stop authentication.
*/
public function getCredentials(Request $request)
{
$csrfToken = $request->request->get('_csrf_token');
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate', $csrfToken))) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
$session = $this->getSession();
if (isset($_SESSION['ADMIN_logged_in']) && intval($_SESSION['ADMIN_logged_in'])){
return $_SESSION['ADMIN_logged_in'];
}
return;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider->loadUserByUserId($credentials);
}
public function checkCredentials($credentials, UserInterface $user)
{
return $user->getUsername() == $credentials;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return null;
}
/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$url = $this->router->generate('app_security_login');
return new RedirectResponse($url);
}
public function supportsRememberMe()
{
return false;
}
}
Tất cả kiểm tra CSRF - kể cả trên biểu mẫu đăng nhập - không thành công khi tôi thêm 5 dòng trong security.yml bắt đầu bằng form_login. Các lỗi tôi nhận được là:
The CSRF token is invalid. Please try to resubmit the form. portalbundle_portal_job
Nguyên nhân:
Khi tôi loại bỏ những 5 dòng, tất cả các mã thông báo CSRF làm việc.
Bạn đã theo dõi tài liệu này: https://symfony.com/doc/current/security/csrf_in_login_form.html? –
không cụ thể, tất cả các biểu mẫu đều bị ảnh hưởng khi đăng nhập. Điều này có liên quan không? – jdog
chỉ để xác nhận, biểu mẫu đăng nhập không có CSRF. Nhưng câu hỏi của tôi đề cập đến tất cả các biểu mẫu trong hệ thống – jdog