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