簡體   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