Silex 检查用户是否在不安全的路由上进行了身份验证
我正在尝试使用Silex中的Silex 检查用户是否在不安全的路由上进行了身份验证,silex,symfony-security,Silex,Symfony Security,我正在尝试使用Silex中的symofny/security包构建一个简单的登录,但是我在身份验证检查方面遇到了一个小问题 结构: / /login /admin /login_check /logout 为了进入/admin路由,需要对用户进行身份验证,如果他没有身份验证,他将被重定向到/login表单,然后根据建议,该表单要求管理员/login\u检查进行身份验证(这都是由symofny的安全防火墙提供的) 防火墙配置: 'security.firewalls' =>
symofny/security
包构建一个简单的登录,但是我在身份验证检查方面遇到了一个小问题
结构:
/
/login
/admin
/login_check
/logout
为了进入/admin
路由,需要对用户进行身份验证,如果他没有身份验证,他将被重定向到/login
表单,然后根据建议,该表单要求管理员/login\u检查
进行身份验证(这都是由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'),
));
}
这会引发错误:令牌存储不包含身份验证令牌。一个可能的原因可能是没有为此URL配置防火墙。
因此,问题是,有没有办法通过本机使用symfony/security
实现这一点(无需任何漫游)?或者,是否有可能在安全区域内创建/login
路由,即使用户未登录(例如,对GET请求进行例外),也可以访问该路由,从而解决问题
更新
我还为
/login
页面添加了防火墙配置,其中有一个选项匿名:true
,这导致不再抛出错误,但是,当我登录到/admin
路由时,方法被授予(“角色\管理员”)
会产生true
,而在/login
路由上,它会导致false
(我仍在那里登录)。您可以通过转储当前令牌轻松了解安全组件的行为
public function index(Request $request, Application $app)
{
var_dump($application['security.token_storage']->getToken());
}
当您没有为登录页面设置匿名
选项时(默认为false
):
当您将登录页面的匿名
选项设置为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
下面的示例描述了在初始代码示例中出现错误的原因
如何共享安全令牌?
要在多个防火墙之间共享安全令牌,必须设置相同的安全令牌
SecurityServiceProvider
为使用模式security.context\u listener.声明的受保护防火墙注册上下文侦听器。
。在您的示例中,它注册为security.context\u listener.admin
。因此,您要使用的上下文名为admin
此外,防火墙上下文密钥存储在会话中,因此每个使用它的防火墙必须将其无状态
选项设置为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\u checker']->isgrated('ROLE\u ADMIN')
安全地检查权限,并在两个防火墙上获得相同的结果。您可以通过转储当前令牌轻松了解安全组件的行为
public function index(Request $request, Application $app)
{
var_dump($application['security.token_storage']->getToken());
}
当您没有为登录页面设置匿名
选项时(默认为false
):
当您将登录页面的匿名
选项设置为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
下面的示例描述了在初始代码示例中出现错误的原因
如何共享安全令牌?
要在多个防火墙之间共享安全令牌,必须设置相同的安全令牌
SecurityServiceProvider
为使用模式security.context\u listener.声明的受保护防火墙注册上下文侦听器。
。在您的示例中,它注册为security.context\u listener.admin
。因此,您要使用的上下文名为admin
此外,防火墙上下文密钥存储在会话中,因此每个使用它的防火墙必须将其无状态
选项设置为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\u checker']->isgrated('ROLE\u ADMIN')
安全地检查权限,并在两个防火墙上获得相同的结果。您太棒了,谢谢!终于有人找时间解释了。在我再次阅读后,我理解了防火墙部分,但在Silex symfony/security文档中,我没有发现任何关于上下文的内容。没关系,我本可以读到symfony的那本。再次感谢。是的,涉及到这件事的文档很差。我只能建议您在回答问题后立即阅读我为silex文档提供的代码,但它仍在等待批准,我们拭目以待。您太棒了,谢谢!终于有人找时间解释了。在我再次阅读后,我理解了防火墙部分,但在Silex symfony/security文档中,我没有发现任何关于上下文的内容。没关系,我本可以读到symfony的那本。再次感谢。是的,涉及到这件事的文档很差。我只能建议您在回答问题后立即阅读我为silex文档提供的代码