来自Symfony 2.3 Security docs:
如果拒绝访问,系统将尝试对用户进行身份验证(例如,将用户重定向到登录页面)。如果用户已登录,将显示403“访问被拒绝”错误页面。有关详细信息,请参阅如何自定义错误页面。
我目前正在为一些路线使用access_control
规则。我想通知匿名用户,如果他们被重定向到登录路线,并显示“您必须登录才能访问该页面”这样的消息。我已经阅读了几次安全文档并且没有找到与此相关的任何内容。我忽略了什么吗?
如果没有,那么当用户被access_control
规则仅停止时,如果他们被重定向到登录(即不是他们',则通知用户的最佳方式是什么?只是在一个未授权的角色)?
修改
为了澄清,我特别询问如何检查重定向是否是由access_control
规则引起的(如果可能的话,最好是在树枝中)。
答案 0 :(得分:56)
经过相当多的研究,我发现了正确的方法。您需要使用Entry Point服务并在防火墙配置中对其进行定义。
此方法不会使用防火墙配置中指定的default page设置进行登录。
<强> security.yml:强>
firewalls:
main:
entry_point: entry_point.user_login #or whatever you name your service
pattern: ^/
form_login:
# ...
<强>的src / Acme公司/ UserBundle /配置/ services.yml 强>
services:
entry_point.user_login:
class: Acme\UserBundle\Service\LoginEntryPoint
arguments: [ @router ] #I am going to use this for URL generation since I will be redirecting in my service
<强>的src / Acme公司/ UserBundle /服务/ LoginEntryPoint.php:强>
namespace Acme\UserBundle\Service;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface,
Symfony\Component\Security\Core\Exception\AuthenticationException,
Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpFoundation\RedirectResponse;
/**
* When the user is not authenticated at all (i.e. when the security context has no token yet),
* the firewall's entry point will be called to start() the authentication process.
*/
class LoginEntryPoint implements AuthenticationEntryPointInterface
{
protected $router;
public function __construct($router)
{
$this->router = $router;
}
/*
* This method receives the current Request object and the exception by which the exception
* listener was triggered.
*
* The method should return a Response object
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$session = $request->getSession();
// I am choosing to set a FlashBag message with my own custom message.
// Alternatively, you could use AuthenticationException's generic message
// by calling $authException->getMessage()
$session->getFlashBag()->add('warning', 'You must be logged in to access that page');
return new RedirectResponse($this->router->generate('login'));
}
}
<强> login.html.twig:强>
{# bootstrap ready for your convenience ;] #}
{% if app.session.flashbag.has('warning') %}
{% for flashMessage in app.session.flashbag.get('warning') %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ flashMessage }}
</div>
{% endfor %}
{% endif %}
答案 1 :(得分:1)
我认为kernel.exception
监听器并设置flash消息可以做到这一点。未经测试的例子:
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class My403ExceptionListener
{
protected $session;
public function __construct(SessionInterface $session)
{
$this->session = $session;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof AccessDeniedHttpException) {
$this->session->getFlashBag()->set('warning', 'You must login to access that page.');
}
}
}
不知道它是否有效或是否正确。您可以将其注册为kernel.event_listener
。或者,您可以更好地使用专用服务并将其设置为firewall config中access_denied_handler
的参数。我认为有很多可能的方法。
答案 2 :(得分:0)
你能不能只有两条登录路线?
例如,在安全配置集
中form_login:
login_path: /login_message
在您的登录控制器中
/**
* @Template()
* @Route("/notauthorized", name="login_message")
*/
public function loginMessageAction()
{
return [];
}
然后在你的loginMessage.html.twg
中<a href="{{ path('login') }}">You must login to access this page.</a>