我在Symfony 2.8.x应用中工作,我需要设置两个安全区域:chat
和admin
。这意味着chat
和admin
将使用相同的登录模板(如果可行,我不需要为此目的设置不同的登录模板)。我在问这里之前已经用Google搜索并且有一些相关的内容出现了,我读了很多关于这个主题的帖子:1,2,3 ,4只是作为他们的一个例子,但我做错了,因为我无法正常工作。这就是/app/config/security.yml
的样子(只是防火墙和access_control代码片段):
security:
....
firewalls:
admin:
pattern: /admin/(.*)
anonymous: ~
form_login:
provider: fos_userbundle
csrf_provider: security.csrf.token_manager
login_path: fos_user_security_login
check_path: fos_user_security_check
use_forward: true
always_use_default_target_path: true
default_target_path: /admin
target_path_parameter: _target_path
use_referer: true
remember_me: true
logout:
target: /admin
remember_me:
secret: '%secret%'
lifetime: 604800 # 1 week in seconds
path: /
chat:
pattern: ^/chat/(.*)
anonymous: ~
form_login:
provider: fos_userbundle
csrf_provider: security.csrf.token_manager
login_path: fos_user_security_login
check_path: fos_user_security_check
use_forward: true
always_use_default_target_path: true
default_target_path: /chat
target_path_parameter: _target_path
use_referer: true
remember_me: true
logout: ~
remember_me:
secret: '%secret%'
lifetime: 604800 # 1 week in seconds
path: /
access_control:
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/resetting$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/resetting$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/, role: ROLE_CHATTER }
- { path: ^/admin/, role: ROLE_ADMIN }
现在这是我app/config/routing.yml
platform_chat:
resource: "@PlatformChatBundle/Controller/"
type: annotation
prefix: /chat/
options:
expose: true
platform_admin:
resource: "@PlatformAdminBundle/Controller/"
type: annotation
prefix: /admin/
options:
expose: true
对于FOSUserBundle
我尝试了这两个(两个都没有成功,每次都是):
#FOSUser
fos_user:
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
#FOSUser
# this second causes doubts to me since I think I will need
# to repeat the same routes for chat prefix but I'm not sure at all
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
prefix: /admin
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /admin/profile
fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /admin/register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /admin/resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /admin/profile
我在app/Resources/FOSUserBundle/views/Security/login.html.twig
覆盖了登录模板。 (如果需要来源,我可以提供仅仅因为没有使帖子比已经发布更长的时间)。
当我调用URL:http://domain.tld/app_dev.php/admin
并尝试登录时出现此错误:
找不到翻译。 上下文:{" id": " Symfony的\元器件\安全\核心\异常\ BadCredentialsException: 不好的信用史。在 /var/www/html/platform-cm/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php:90\nStack 跟踪:\ N#0
(如果需要,我可以提供完整的堆栈跟踪)
这对我来说很奇怪,但由于我已经仔细检查了凭据,因此可能导致配置错误。
当我拨打网址:http://domain.tld/app_dev.php/chat
并尝试登录时,我获得了Access Denied
,但它是正确的,因为我被重定向到http://domain.tld/app_dev.php/admin/
。可以给我一些关于这种配置的帮助吗?我陷入困境,因为这个而无法前进
第二种方法
这是第二种方法,基于使用听众的@heah建议但是也没有工作我仍然得到相同的"错误的凭据"消息,根本无法登录。我已将routing.yml
更改为此:
#FOSUser
fos_user:
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
我已将security.yml
更改回此:
安全性: ... 防火墙: 管理员: 模式:^ / 匿名:〜 form_login: 提供者:fos_userbundle csrf_provider:security.csrf.token_manager login_path:fos_user_security_login check_path:fos_user_security_check
# if true, forward the user to the login form instead of redirecting
use_forward: true
# login success redirecting options (read further below)
always_use_default_target_path: true
default_target_path: /admin
target_path_parameter: _target_path
use_referer: true
remember_me: true
logout:
target: /admin
remember_me:
secret: '%secret%'
lifetime: 604800 # 1 week in seconds
path: /
access_control:
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/resetting$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/resetting$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/, role: ROLE_CHATTER }
- { path: ^/admin/, role: ROLE_ADMIN }
然后我按照security.interactive_login
中的建议为app/config/config.yml
事件定义了一个监听器:
parameters:
account.security_listener.class: PlatformAdminBundle\Listener\SecurityListener
然后在app/config/services.yml
:
services:
account.security_listener:
class: %account.security_listener.class%
arguments: ['@security.context', '@session']
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }
最后这里是src/PlatformAdminBundle/Listener/SecurityListener.php
的类定义:
namespace PlatformAdminBundle\Listener;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class SecurityListener
{
public function __construct(SecurityContextInterface $security, Session $session)
{
$this->security = $security;
$this->session = $session;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $this->security->getToken()->getUser();
var_export($user);
}
}
我正在运行同样的问题,也许我做错了什么,我没有看到,但我接受任何想法。这可能有什么问题?
第3种方法
我对我的代码进行了审核,并在@heah建议之后稍微改变了一下。所以,现在security.yml
如下:
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/, role: ROLE_CHATTER }
- { path: ^/admin/, role: ROLE_ADMIN }
services.yml
的更改基本上修复了参数,因为security.context
已在Symfony 2.6+中被拆分,尽管我根本不使用它:
services:
...
account.security_listener:
class: %account.security_listener.class%
arguments: ['@security.authorization_checker']
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }
最后是班级PlatformAdminBundle/Listener/SecurityListener.php
的变化:
namespace Clanmovil\PlatformAdminBundle\Listener;
use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class SecurityListener
{
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->security = $authorizationChecker;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
if ($this->security->isGranted('ROLE_ADMIN')) {
// this is something for testing
throw new AccessDeniedException(
'Access Denied. You are ADMIN'
);
} elseif ($this->security->isGranted('ROLE_CHATTER')) {
// this is something for testing
throw new AccessDeniedException(
'Access Denied. You are CHATTER'
);
}
}
}
当我以ROLE_CHATTER
用户身份登录时,一切似乎都有效,因为我收到了AccessDenied异常,但当我尝试以ROLE_ADMIN
用户身份登录时,它停止工作,我又回到初始错误:Bad credentials
,这是为什么?我疯了!!
答案 0 :(得分:1)
您需要启用翻译:
# config.yml
framework:
translator: ~
...
fos_user:
db_driver: orm # or mongodb|couchdb|propel
firewall_name: global
user_class: AppBundle\Entity\User
请参阅https://symfony.com/doc/master/bundles/FOSUserBundle/index.html
#security.yml
security:
firewalls:
# ...
global:
pattern: ^/
anonymous: true
provider: fos_userbundle
form_login:
csrf_token_generator: security.csrf.token_manager
remember_me: true
default_target_path: root
logout:
path: fos_user_security_logout
target: root
remember_me:
secret: '%secret%'
lifetime: 604800 # 1 week in seconds
access_control:
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/chat/, role: ROLE_CHATTER }
- { path: ^/admin/, role: ROLE_ADMIN }
请参阅http://symfony.com/doc/current/components/security/authentication.html
此外,您应使用相同的防火墙,因为它们共享相同的配置,并且您已根据用户角色定义了访问控制。
您只需要为' /'创建一个核心控制器。 as:
# routing.yml
root:
path: /
defaults: { _controller: Your\Namespace\Controller\RootController::rootAction }
和
namespace Your\Namespace\Controller;
use Symfony\Bundle\FrameworkBundle\Controller;
class RootControler extends Controller
{
public function rootAction()
{
$security = $this->get('security.authorization_checker');
if ($security->isGranted('ROLE_ADMIN')) {
return $this->redirectToRoute('your_admin_root');
}
if ($security->isGranted('ROLE_CHATTER')) {
return $this->redirectToRoute('your_chatter_route');
}
return $this->redirectToRoute('fos_user_security_login');
}
}
答案 1 :(得分:0)
问题可能出在路由中。由于在这两种情况下您只使用FOSUserBundle中的一个进行身份验证,因此您应该尝试为每个防火墙创建两个不同的路由,例如:
#FOSUser
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
prefix: /admin
#FOSUser
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
prefix: /chat