可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I use Symfony Standard 2.0.0BETA1 and tried to configure http_basic authentication exactly the same as in this book chapter
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
providers:
main:
users:
foo: { password: testing, roles: ROLE_USER }
firewalls:
main:
pattern: /.*
http_basic: true
logout: true
access_control:
- { path: /.*, role: ROLE_USER }
Problem is when I try to open a page and i submit user name "foo" and password "testing" it simply loops and ask me for credential infinitely or display error page.
Steps to reproduce issue:
- Copy security configuration from http://symfony.com/doc/current/book/security/overview.html#configuration and past it to security.yml file
- Refresh app home page
- Enter valid credentials
Expected behavior is to see home page but instead credentials prompt is shown.
Does anyone know why that happens and how to fix it?
回答1:
The http basic authentication is broken with PHP as cgi/fastCGI under Apache
There is a workaround:
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>
Source: symfony github issue
回答2:
The problem is you restricted access to /.*
, which means all paths, to only users who have the role ROLE_USER.
Say your login path is /login
, the user tries to access any other path and is redirected to the login path. The login path (/login
) will be matched by the access control pattern /.*
. The user will then be denied of access because he doesn't have the role ROLE_USER right now. The security component will redirect the user again to the login form so he can authenticate to get the role, which is restricted, and will redirect the user to the login form to authenticate and so on.
Here's a simple solution to avoid this problem. You can allow access to the login form to anonymous user with the activation of the anonymous user configuration and a new access control item. Add this below main
in the firewalls
configuration to enable anonymous user:
security:
firewalls:
main:
anonymous: true
And add a new access control item to allow anonymous user to acces the /login
pattern:
access_control:
- { path: /login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /.*, role: ROLE_USER }
The order is important here since the rule is: first path matched wins. So the /login
path must be above your pattern for other path /.*
. This should resolves you redirect loop.
The documentation of Symfony about security is being rewritten right now and will talk more in details about this problem. It is in the symfony-docs github repository under the security branch.
Regards,
Matt
回答3:
The same problem still occurs in the current version (Symfony version 2.1.8).
It's because of the special way that Apache + PHP as FastCGI handles HTTP auth variables.
At least, the fix for the current version is a little simplier than it was before (as compared to @Teo.sk's answer), and the instructions are available directly hardcoded as comments in the file vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/ServerBag.php
of the framework:
/*
* 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]
*/
In short, to fix it, all you have to do is to add the following lines to the .htaccess
file of the web/
folder of your application:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
New info (2013-05-01): now I'm using Symfony version 2.2.1 and for the fix to work I had to add those two lines of codes right below the following line of web/.htaccess
:
RewriteEngine On
回答4:
you dont't need to modify your SymfonyProject, you need also change apache2 configuration.
sudoedit /etc/apache2/sites-enabled/[your site].conf
insert
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
keep to restart apache2
enjoy :)
回答5:
i use my boundle route:
- { path: /correspondencia/recepcion/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /correspondencia/recepcion, role: ROLE_ADMIN }
without the last slash
wrong
/correspondencia/recepcion/
good
/correspondencia/recepcion