[英]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.