2016-03-27 3 views
0

У меня возникла проблема с пользовательским входом для входа в систему Symfony, вдохновленным учебником «Как создать традиционную форму входа в систему» ​​из поваренной книги Symfony. Все работает нормально, пока я не вхожу в систему с/логином. Тогда каждый маршрут, который я хочу перенаправить, вызывает бесконечный цикл. Может, я что-то упустил?Безопасность Symfony 3 После входа в систему существует бесконечное перенаправление

//security.yml безопасности:

encoders: 
     AppBundle\Entity\User: 
      algorithm: bcrypt 

providers: 
    mysql: 
     entity: 
      class: AppBundle:User 
      property: username 


firewalls: 
    # disables authentication for assets and the profiler, adapt it according to your needs 
    dev: 
     pattern: ^/(_(profiler|wdt)|css|images|js)/ 
     security: false 

    main: 
     anonymous: ~ 
     form_login: 
      login_path: login 
      check_path: login_check 
     logout: 
      path: logout 


access_control: 
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/, roles: IS_AUTHENTICATED_FULLY } 

//routing.yml

index: 
path:/
defaults: { _controller: AppBundle:Main:main } 
app: 
    resource: "@AppBundle/Controller/" 
    type:  annotation 

//SecurityController.php

<?php 

namespace AppBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 

class SecurityController extends Controller 
{ 
/** 
* @Route("/login", name="login") 
*/ 
public function loginAction() { 
    $authenticationUtils = $this->get("security.authentication_utils"); 

    $error = $authenticationUtils->getLastAuthenticationError(); 
    $name = $authenticationUtils->getLastUsername(); 

    return $this->render(
     ':security:login.html.twig', 
     ["name" => $name, "error" => $error] 
    ); 
} 
/** 
* @Route("/login_check", name="login_check") 
*/ 
public function loginCheckAction() { 
} 
/** 
* @Route("/logout",name="logout") 
*/ 
public function logoutAction() { 
} 

} 

//login.twig.html

{% if error %} 
<div>{{ error.messageKey|trans(error.messageData, 'security') }}</div> 
{% endif %} 

<form action="{{ path('login_check') }}" method="post"> 
    <label for="username">Username:</label> 
    <input type="text" id="username" name="_username" value="{{ name }}" /> 

    <label for="password">Password:</label> 
    <input type="password" id="password" name="_password" /> 
    <input type="hidden" name="_target_path" value="/" /> 

    <button type="submit">login</button> 
</form> 

ответ

0

Вы должны изменить

access_control: 
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } 

в

access_control: 
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY } 

иметь login_check за брандмауэром.

Ваш routing.yml кажется странным для меня, не могли бы вы разместить свой контроллер и свою ветку, чтобы увидеть ваши маршруты?

+0

Проверьте, пожалуйста, – vnarek

0

Причина в том, что сценарий Войти пересылает вас на страницу входа в систему, когда он видит, что вы вошли в нее ретрансляция вас реферера .. что страница Войти .. и так далее ..

Чтобы обойти это, у вас есть несколько вариантов.

1) Вы можете установить целевой путь по умолчанию в своем app/config/security.yml, чтобы каждый раз, когда пользователь регистрировался, они перенаправляются на конкретный маршрут. Проблема с этим подходом заключается в том, что использование always_use_default_target_path будет означать, что он никогда не перейдет на ссылочную страницу, но если вы его не используете и вы не выполните попытку входа в систему, он направит вас на страницу входа в систему (реферер в эта точка).

firewalls: 
    //.. 
    main: 
     anonymous: ~ 
     form_login: 
      default_target_path: **default_route** 
      always_use_default_target_path: true 
      login_path: login 
      check_path: login_check 
     logout: 
      path: logout 

2) Вы можете установить поле в форме входа в систему, которая устанавливает цели по умолчанию путь к, который может быть ссылающейся или указан один в зависимости от случая. Эта проблема с этим подходом заключается в том, что пользователю необходимо будет пройти процесс регистрации, который будет перенаправлен, поэтому, если пользователи вернутся на страницу входа в систему, по какой-то причине они будут вынуждены снова войти в систему перед перенаправлением.

//... 

{% set referer = app.request.headers.get('referer') %} 
{% set targetPath = referer is not null and referer != url('login') 
    ? referer 
    : path('**default_route**') 
%} 

<form action="{{ path('login_check') }}" method="post"> 
    //... 

    <input type="hidden" name="_target_path" value="{{ targetPath }}" /> 
</form> 

3) Моя рекомендация Вы можете установить флажок в контроллере авторизации, который можно проверить, если пользователь уже вошел в систему, а затем перенаправляет пользователя на конкретном маршруте. Преимущество этого в том, что он остановит пользователей, которые уже вошли в форму входа в систему, но все равно позволит вам пересылать пользователя на ссылочную страницу/маршрут, когда это возможно.

/** 
* @Route("/login", name="login") 
*/ 
public function loginAction() { 
    if (null !== $this->getUser()) { 
     return new RedirectResponse($this->generateUrl('**default_route**')); 
    } 

    //... 
} 
+0

Все еще ничего. Я пробовал все рекомендации без каких-либо улучшений. – vnarek

0

@qooplmao Я не понимаю, почему вы сказали «ссылающаяся .. что страница Войти» реферер является «/» ведьма не страница Логина («/ Логин»), но маршрут где-то в mainController. Если маршрут/логин соответствует до/это будет нормально, нет?

Ранее Маршруты всегда Win тогда routing.yml может быть

login: 
    resource: "@AppBundle/Controller/SecurityController.php" 
    type:  annotation 
app: 
    resource: "@AppBundle/Controller/" 
    type:  annotation 
index: 
    path:/
    defaults: { _controller: AppBundle:Main:main } 

Вы можете удалить индекс тоже, если вы используете аннотации в главном контроллере.

+0

Не работает и для меня. index используется как какое-либо исправление для установки маршрута по умолчанию. AppBundle: Main: основная аннотация определяется как/page/{slug} со значением по умолчанию для slug – vnarek

+0

Что сказать панель инструментов отладки? – lemairep

+0

Просто для того, чтобы понять. Вы хотите, чтобы ваш сайт полностью находился за брандмауэром? – lemairep

0

попробовать, как это: security.yml безопасности:

encoders: 
     AppBundle\Entity\User: 
      algorithm: bcrypt 

providers: 
    mysql: 
     entity: 
      class: AppBundle:User 
      property: username 


firewalls: 
    # disables authentication for assets and the profiler, adapt it according to your needs 
    dev: 
     pattern: ^/(_(profiler|wdt)|css|images|js)/ 
     security: false 

    main: 
     anonymous: ~ 
     form_login: 
      login_path: login 
      check_path: login_check 
     logout: 
      path: logout 


access_control: 
    - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/, roles: IS_AUTHENTICATED_FULLY } 

routing.yml

login: 
    resource: "@AppBundle/Controller/SecurityController.php" 
    type:  annotation 
app: 
    resource: "@AppBundle/Controller/" 
    type:  annotation 

SecurityController.php

<?php 

namespace AppBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 

class SecurityController extends Controller 
{ 
/** 
* @Route("/login", name="login") 
*/ 
public function loginAction() { 
    $authenticationUtils = $this->get("security.authentication_utils"); 

    $error = $authenticationUtils->getLastAuthenticationError(); 
    $name = $authenticationUtils->getLastUsername(); 

    return $this->render(
     ':security:login.html.twig', 
     ["name" => $name, "error" => $error] 
    ); 
} 
/** 
* @Route("/login_check", name="login_check") 
*/ 
public function loginCheckAction() { 
} 
/** 
* @Route("/logout",name="logout") 
*/ 
public function logoutAction() { 
} 

} 

login.twig.html

В вашем mainController нужно использовать аннотаций маршруты и заменить, например «THE_NAME_OF_THE_ROUTE_YOU_WANT_TO_GO» на «/» страницы, если это маршрут вы хотите идти ...

помощь здесь: http://symfony.com/doc/current/book/routing.html

+0

Теперь, после перезагрузки моего ноутбука и входа в систему, я перенаправлен на ** localhost: 8000/page **, но это пустая страница, а затем проблема возникает снова. Инфинитная загрузка страницы по любому запросу, который я пытаюсь сделать. даже маршруты, которые не существуют, вызывают бесконечную загрузку страницы. – vnarek

+0

Очистите кеш после изменений? – lemairep

+0

Не могли бы вы попытаться удалить брандмауэр и протестировать ваш maincontoller с/страницей, так как проблема с вашим контроллером ... – lemairep

1

Хорошо, так я наконец, проблема, и проблема не была в маршрутах или безопасности вообще. Я просто сделал сериализацию в User Entity неправильно. Некоторые misspell symfony не упоминаются в отладчике. Странно, что это вызвало такое поведение. В любом случае спасибо всем, кто пытался мне помочь.