我使用Symfony Standard 2.0.0ETA1,并尝试配置与本书章节完全相同的http_basic身份验证
security:
encoders:
SymfonyComponentSecurityCoreUserUser: plaintext
providers:
main:
users:
foo: { password: testing, roles: ROLE_USER }
firewalls:
main:
pattern: /.*
http_basic: true
logout: true
access_control:
- { path: /.*, role: ROLE_USER }
问题是,当我试图打开一个页面并提交用户名"foo"和密码"testing"时,它只是循环并无限地要求我提供凭据或显示错误页面。
复制问题的步骤:
- 从复制安全配置http://symfony.com/doc/current/book/security/overview.html#configuration并将其传递到security.yml文件
- 刷新应用主页
- 输入有效凭据
预期的行为是查看主页,但显示凭据提示。
有人知道为什么会发生这种情况以及如何解决吗?
Apache 下的http基本身份验证被PHP破坏为cgi/fastCGI
有一个变通方法:
app_dev.php
if( !isset($_SERVER['PHP_AUTH_USER']) )
{
if (isset($_SERVER['HTTP_AUTHORIZATION']) && (strlen($_SERVER['HTTP_AUTHORIZATION']) > 0))
{
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
if( strlen($_SERVER['PHP_AUTH_USER']) == 0 || strlen($_SERVER['PHP_AUTH_PW']) == 0 )
{
unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
}
}
}
web/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
来源:symfony github问题
问题是您将对/.*
(即所有路径(的访问权限限制为仅具有角色role_USER的用户。
假设您的登录路径为/login
,则用户尝试访问任何其他路径,并被重定向到登录路径。登录路径(/login
(将与访问控制模式/.*
相匹配。然后,用户将被拒绝访问,因为他现在没有角色role_user。安全组件将再次将用户重定向到登录表单,以便他可以进行身份验证以获得角色,这是受限制的,并将用户重定向至登录表单以进行身份验证,依此类推
这里有一个简单的解决方案来避免这个问题。通过激活匿名用户配置和新的访问控制项,您可以允许匿名用户访问登录表单。将其添加到firewalls
配置中的main
下方,以启用匿名用户:
security:
firewalls:
main:
anonymous: true
并添加一个新的访问控制项,允许匿名用户访问/login
模式:
access_control:
- { path: /login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /.*, role: ROLE_USER }
这里的顺序很重要,因为规则是:第一条匹配的路径获胜。因此,对于其他路径/.*
,/login
路径必须高于您的模式。这将解决重定向循环。
Symfony关于安全性的文档现在正在重写中,并将详细讨论这个问题。它位于安全分支下的symfony docs github存储库中。
谨致问候,Matt
在当前版本(Symfony 2.1.8版本(中仍然会出现同样的问题。
这是因为Apache+PHP作为FastCGI处理HTTP身份验证变量的特殊方式。
至少,当前版本的修复程序比以前简单了一点(与@Teo.sk的答案相比(,并且这些指令可以直接硬编码为框架的vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/ServerBag.php
文件中的注释:
/*
* php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
* For this workaround to work, add these lines to your .htaccess file:
* RewriteCond %{HTTP:Authorization} ^(.+)$
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
*
* A sample .htaccess file:
* RewriteEngine On
* RewriteCond %{HTTP:Authorization} ^(.+)$
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
* RewriteCond %{REQUEST_FILENAME} !-f
* RewriteRule ^(.*)$ app.php [QSA,L]
*/
简而言之,要修复它,您所要做的就是将以下行添加到应用程序的web/
文件夹的.htaccess
文件中:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
新信息(2013-05-01(:现在我使用Symfony 2.2.1版本,为了修复问题,我不得不在web/.htaccess
:的下面添加这两行代码
RewriteEngine On
您不需要修改SymfonyProject,还需要更改apache2配置。
sudoedit/etc/apache2/sites-enabled/[your-site].conf
插入
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
保持重新启动apache2
享受:(
我使用我的弹跳路线:
- { path: /correspondencia/recepcion/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /correspondencia/recepcion, role: ROLE_ADMIN }
没有最后一个斜杠错误的
/correspondencia/recepcion/
良好
/correspondencia/recepcion