我正在尝试使用symofny/security
Silex 中的包构建一个简单的登录,但是我在身份验证检查方面遇到了一个小问题。
结构:
/
/login
/admin
/login_check
/logout
为了到达/admin
路由,用户需要进行身份验证,如果没有,他将被重定向到/login
表单,然后按照建议要求admin/login_check
进行身份验证(所有这些都由 symofny 的安全防火墙提供)。
防火墙配置:
'security.firewalls' => array(
'login' => array(
'pattern' => '^/login$',
),
'admin' => array(
'pattern' => '^/admin',
'http' => true,
'form' => array(
'login_path' => '/login',
'check_path' => '/admin/login'
),
'logout' => array(
'logout_path' => '/admin/logout',
'invalidate_session' => true
),
'users' => ...
),
)
一切正常,但用户可以进入/login
路线,即使他已经通过身份验证,这还不错,但我想避免它。我厌倦了检查用户身份验证状态,但我想它不起作用,因为我正在/login
控制器上检查它,该控制器不在网站的“安全”区域。
这是代码:
public function index(Request $request, Application $app)
{
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
return $app->redirect($app['url_generator']->generate('admin'));
}
return $app['twig']->render('login/index.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
}
这引发了一个错误:The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.
那么,问题是,有没有办法在symfony/security
本地使用(没有任何走动)来做到这一点?或者是否有可能/login
在安全区域内创建路由并有可能访问它 - 即使用户未登录(例如,为 GET 请求设置例外)这将解决问题?
更新
我还为/login
带有 option 的页面添加了防火墙配置anonymous: true
,这导致不再抛出错误,但是,当我登录/admin
路由时,方法isGranted('ROLE_ADMIN')
结果为true
,而在/login
路由上它导致false
(我是仍然在那里登录)。
您可以通过转储当前令牌轻松了解安全组件的行为。
public function index(Request $request, Application $app)
{
var_dump($application['security.token_storage']->getToken());
}
当您没有anonymous
为登录页面设置选项时(默认为false
):
null
当您将anonymous
登录页面的选项设置为true
:
object(Symfony\Component\Security\Core\Authentication\Token\AnonymousToken)
private 'secret' => string 'login' (length=5)
private 'user' (Symfony\Component\Security\Core\Authentication\Token\AbstractToken) => string 'anon.' (length=5)
private 'roles' (Symfony\Component\Security\Core\Authentication\Token\AbstractToken) =>
array (size=0)
empty
private 'authenticated' (Symfony\Component\Security\Core\Authentication\Token\AbstractToken) => boolean true
private 'attributes' (Symfony\Component\Security\Core\Authentication\Token\AbstractToken) =>
array (size=0)
empty
以下示例描述了您在初始代码示例中出错的原因。
要在多个防火墙之间共享安全令牌,您必须设置相同的Firewall Context。
SecurityServiceProvider
为您使用 pattern 声明的受保护防火墙注册上下文侦听器security.context_listener.<name>
。在您的示例中,它注册为security.context_listener.admin
. 因此,您要使用的上下文名为admin
。
此外,一个防火墙上下文键存储在会话中,因此每个使用它的防火墙都必须将其stateless
选项设置为false
.
更重要的是,要在登录页面上调用身份验证,该anonymous
选项必须设置为true
'security.firewalls' => array(
'login' => array(
'context' => 'admin',
'stateless' => false,
'anonymous' => true,
'pattern' => '^/login$',
),
'admin' => array(
'context' => 'admin',
'stateless' => false,
'pattern' => '^/admin',
'http' => true,
'form' => array(
'login_path' => '/login',
'check_path' => '/admin/login'
),
'logout' => array(
'logout_path' => '/admin/logout',
'invalidate_session' => true
),
'users' => ...
),
)
更改后,如果您登录管理面板和登录页面,您将获得一个Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
作为令牌的实例,Symfony\Component\Security\Core\Authentication\Token\AnonymousToken
如果您未登录。
因此,您可以安全地检查权限$app['security.authorization_checker']->isGranted('ROLE_ADMIN')
并在两个防火墙上获得相同的结果。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句