繁体   English   中英

Symfony 3安全性登录后,存在无限重定向

[英]Symfony 3 security After login there is an infinite redirect

我有自定义symfony安全登录的问题,受Symfony cookbook教程“如何构建传统登录表单”的启发。 一切正常,直到我从/ login route登录。 然后我想要重定向到的每个路由都会导致无限循环。 也许我错过了什么?

//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>

好的,所以我终于找到了问题,问题根本不在路线或安全性。 我刚刚在User Entity中序列化了错误。 调试器中没有提到一些拼写错误的symfony。 它引起这种行为很奇怪。 无论如何,感谢任何试图帮助我的人。

你应该改变

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

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

在防火墙后面有login_check。

你的routing.yml对我来说似乎很奇怪,你可以发布你的控制器和你的树枝来看你的路线吗?

原因是因为登录脚本将您转发到登录页面,当它看到您已登录时,它会将您转发给引用者..这是登录页面......等等。

要解决这个问题,您有几个选择。

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**'));
    }

    //...
}

@qooplmao我不明白为什么你说“引用者..这是登录页面”引用者是“/”女巫不是登录页面(“/ login”)而是在mainController中的某个地方。 如果/ login路由匹配之前/它会没有问题吗?

早期的路由总是赢,然后routing.yml可以

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

如果在主控制器中使用注释,也可以删除索引。

尝试这样:security.yml security:

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

{% 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="{{ path('THE_NAME_OF_THE_ROUTE_YOU_WANT_TO_GO') }}" />

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

在你的mainController中需要使用注释路由并将'THE_NAME_OF_THE_ROUTE_YOU_WANT_TO_GO'替换为'/ page',如果它是你要去的路线...

这里有一些帮助: http//symfony.com/doc/current/book/routing.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM