【问题标题】:Multiple dynamic firewalls and CAS servers in Symfony2Symfony2 中的多个动态防火墙和 CAS 服务器
【发布时间】:2013-12-29 12:02:25
【问题描述】:

我正在 Symfony 中开发一个应用程序来管理多所学校。该应用程序有多个数据库,每个学校一个,以及多个 CAS 服务器。

如果我只管理一所学校,配置是这样的:

# config.yml
be_simple_sso_auth:
    admin_sso:
        protocol:
            id: cas
            version: 2
        server:
            id: cas
            login_url: https://cas01.example.com/SCHOOLID/login
            logout_url: https://cas01.example.com/SCHOOL_ID/logout
            validation_url: https://cas01.example.com/SCHOOL_ID/serviceValidate

# security.yml
firewalls:
    school:
        pattern: ^/school/.*$
        trusted_sso:
            manager: admin_sso
            login_action: false 
            logout_action: false 
            create_users: true
            created_users_roles: [ROLE_USER, ROLE_ADMIN]
            login_path: /school/login
            check_path: /school/login_check
        logout:
            path:   /school/logout
            target: /school

一所学校一切正常。

各学校通过路径app.com/school/ID访问应用,例如 app.com/school/29、app.com/school/54...

我想知道是否有办法根据 ID 设置多个动态防火墙。并使用此 ID 重定向每个 CAS URL:

https://cas01.example.com/school_29/login, https://cas01.example.com/school_54/login ...

------------ 2012 年 13 月 12 日更新 -----------

我创建了一个新文件:app/config/cas.php,并添加了一些 CAS 服务器设置

# CAS 14
$container->loadFromExtension('be_simple_sso_auth', array(
    'cas_14' => array(
        'protocol' => array(
            'id' => 'cas',
            'version' => '2'
        ),
        'server' => array(
            'id' => 'cas',
            'login_url' => 'https://cas01.example.com/14/login',
            'logout_url' => 'https://cas01.example.com/14/logout',
            'validation_url' => 'https://cas01.example.com/14/serviceValidate',
        ),
    ),

));

# CAS 15
$container->loadFromExtension('be_simple_sso_auth', array(
    'cas_15' => array(
        'protocol' => array(
            'id' => 'cas',
            'version' => '2'
        ),
        'server' => array(
            'id' => 'cas',
            'login_url' => 'https://cas01.example.com/15/login',
            'logout_url' => 'https://cas01.example.com/15/logout',
            'validation_url' => 'https://cas01.example.com/15/serviceValidate',
        ),
    ),

));

我在 config.yml 中导入这个文件

imports:
    - { resource: parameters.yml }
    - { resource: cas.php }
    - { resource: security.yml }

我为每所学校添加了一个新的防火墙:

firewalls:
    backend_14:
        pattern: ^/backend/school/14/.*$
        trusted_sso:
            manager: cas_14
            login_action: false #BeSimpleSsoAuthBundle:TrustedSso:login
            logout_action: false #BeSimpleSsoAuthBundle:TrustedSso:logout
            create_users: true
            created_users_roles: [ROLE_USER, ROLE_ADMIN]
            login_path: /backend/school/14/login
            check_path: /backend/school/14/login_check
        logout:
            path:   /backend/school/logout
            target: /backend

    backend_15:
        pattern: ^/backend/school/15/.*$
        trusted_sso:
            manager: cas_15
            login_action: false #BeSimpleSsoAuthBundle:TrustedSso:login
            logout_action: false #BeSimpleSsoAuthBundle:TrustedSso:logout
            create_users: true
            created_users_roles: [ROLE_USER, ROLE_ADMIN]
            login_path: /backend/school/15/login
            check_path: /backend/school/15/login_check
        logout:
            path:   /backend/school/logout
            target: /backend

一切顺利!

现在我正在尝试从 Entity School 生成所有 cas.php 配置动态。首先我尝试在 SchoolController 中创建一个方法

public function loadCasConfig()
{
    $em = $this->getDoctrine()->getManager();

    $schools= $em->getRepository('SchoolBundle:School')
                  ->findBy(array(), array('name'=> 'ASC'));


    foreach ($schools as $school) {

        $cas_name = 'cas_'.$school->getId();

        $container->loadFromExtension('be_simple_sso_auth', array(
            "$cas_name" => array(
                'protocol' => array(
                    'id' => 'cas',
                    'version' => '2'
                ),
                'server' => array(
                    'id' => 'cas',
                    'login_url' => "https://cas01.example.com/$school->getId()/login",
                    'logout_url' => "https://cas01.example.com/$school->getId()/logout",
                    'validation_url' => "https://cas01.example.com/$school->getId()/serviceValidate",
                ),
            ),

        ));

    }
}

并在 cas.php 文件中调用它

<?php   

use Comp\BackendBundle\Controller\SchoolController;

SchoolController::loadCasConfig();

但我有这个例外:

FileLoaderLoadException: Cannot import resource     
"C:\wamp\www\comp\app/config\cas.php" from     
"C:\wamp\www\comp\app/config\config.yml". (Runtime Notice: Non-static method     
Comp\BackendBundle\Controller\SchoolController::loadCasConfig() should not be     
called statically, assuming $this from incompatible context in     C:\wamp\www\comp\app\config\cas.php line 5)

:(。然后我尝试在cas.php文件中插入方法代码:

use Doctrine\ORM\EntityManager;
use Comp\SchoolBundle\Entity\School;

$em = $this->getDoctrine()->getManager();

$schools= $em->getRepository('SchoolBundle:School')
              ->findBy(array(), array('name'=> 'ASC'));


foreach ($schools as $school) {

    $cas_name = 'cas_'.$school->getId();

    $container->loadFromExtension('be_simple_sso_auth', array(
        "$cas_name" => array(
            'protocol' => array(
                'id' => 'cas',
                'version' => '2'
            ),
            'server' => array(
                'id' => 'cas',
                'login_url' => "https://cas01.example.com/$school->getId()/login",
                'logout_url' => "https://cas01.example.com/$school->getId()/logout",
                'validation_url' => "https://cas01.example.com/$school->getId()/serviceValidate",
            ),
        ),

    ));

}

现在我有了:

FatalErrorException: Error: Call to undefined method 
Symfony\Component\DependencyInjection\Loader\PhpFileLoader::getDoctrine() in 
C:\wamp\www\comp\app\config\cas.php line 11

我想知道如何动态生成文件 cas.php,从数据库中获取数据。

【问题讨论】:

  • 为什么需要多个防火墙?难道不能通过相同的登录/登录检查页面路由每个登录,然后从接收页面路由回复吗?
  • public function loadCasConfig() 不是静态方法。创建一个静态的..然后调用。喜欢: public static function callme(){ $my = new static;返回 $my->loadCasConfig(); }

标签: php security symfony authentication dependency-injection


【解决方案1】:

代码示例:

public function registerContainerConfiguration(LoaderInterface $loader)
{
    $loader->load(__DIR__.'/config/sites/' . $this->_activeSite . '/config.yml');
    $configPath = __DIR__ . '/config/sites/' . $this->_activeSite . '/config_' . $this->getEnvironment() . '.yml';
    if (file_exists($configPath)) {
        $loader->load($configPath);
    }

    $loader->load(__DIR__.'/config/servers/' . $this->getServer() . '.yml');
    $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');

    //per-site overrides
    if (file_exists(__DIR__.'/config/sites/local_' . $this->_activeSite . '.yml')) {
        $loader->load(__DIR__.'/config/sites/local_' . $this->_activeSite . '.yml');
    }
}

【讨论】:

    【解决方案2】:

    当一个平台被多个网站使用时,我们遇到了类似的问题,因此我们有解决方法,现在每个网站都有自己的 security.yml 导入主要的 security.yml

    【讨论】:

    • 是的,但是你添加新网站的时候必须手动写这个security.yml??你能粘贴示例代码吗?
    • 是的,你需要手动编写(但可能你可以有一些虚拟文件用于自动生成)
    【解决方案3】:

    公共函数 loadCasConfig() 不是静态方法。创建一个静态的..然后调用。

    像这样:

    public function loadCasConfig()
    {
        $em = $this->getDoctrine()->getManager();
    
        $schools= $em->getRepository('SchoolBundle:School')
                      ->findBy(array(), array('name'=> 'ASC'));
    
    
        foreach ($schools as $school) {
    
            $cas_name = 'cas_'.$school->getId();
    
            $container->loadFromExtension('be_simple_sso_auth', array(
                "$cas_name" => array(
                    'protocol' => array(
                        'id' => 'cas',
                        'version' => '2'
                    ),
                    'server' => array(
                        'id' => 'cas',
                        'login_url' => "https://cas01.example.com/$school->getId()/login",
                        'logout_url' => "https://cas01.example.com/$school->getId()/logout",
                        'validation_url' => "https://cas01.example.com/$school->getId()/serviceValidate",
                    ),
                ),
    
            ));
    
        }
    }
    
    public static function loadCasConfigStatic(){ 
       $my = new static; 
       return $my->loadCasConfig(); 
    } 
    

    然后(你的 cas.php):

    <?php   
    
    use Comp\BackendBundle\Controller\SchoolController;
    
    SchoolController::loadCasConfigStatic();
    

    【讨论】:

      猜你喜欢
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      相关资源
      最近更新 更多