поставщик удостоверений saml2 в Symfony2


Я должен внедрить и интегрировать поставщика удостоверений SAML2 (IDP) с существующим приложением Symfony 2.

Я нашел некоторый пакет, реализующий Поставщика услуг (SP), но не поставщика удостоверений, поэтому я думаю, что могу использовать библиотеку SimpleSAMLphp. Есть ли другие решения?

Как я могу интегрировать свою логику поставщика услуг пользователя с SimpleSAMLphp?

Author: Gottlieb Notschnabel, 2015-02-15

2 answers

ОБНОВЛЕНИЕ

Как отметил Милош Томич в своем комментарии, воздушный корабль/lightsaml заменяется lightsaml/sp-bundle. Вы можете найти введение здесь.

+++++++++++++++++++++++++++

Недавно я настроил решение SAML, используя Simplesamlphp в качестве IDP и samlspbundle в качестве SP, и все работает хорошо.

Я рекомендую сначала установить Simplesamlphp, следуя этой хорошей документации здесь.

Как только вы запустите IDP, вы увидите страницу приветствия и вкладку "Федерация" (или что-то в этом роде, моя установка на немецком языке). Там вы должны увидеть один вариант "Метаданные SAML 2.0 IdP". Перейдите по этой ссылке и скопируйте показанный XML-файл в отдельный файл и сохраните этот файл.

На стороне symfony я создал новый пакет и назвал его "Samlbundle". Загрузите и установите SamlSPBundle, как описано в их документации (Шаг 1 и шаг 2).

Создайте свой класс состояния/пользователя единого входа (Шаг 3). Вот пример того, как я это сделал:

namespace SamlBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity
 * @ORM\Table(name="samlUser")
 */
class SamlUser extends \AerialShip\SamlSPBundle\Entity\SSOStateEntity implements UserInterface
{

/**
 * initialize User object and generates salt for password
 */
public function __construct()
{
    if (!$this->userData instanceof UserData) {
        $this->userData  = new UserData();
    }
    $this->setRoles('ROLE_USER');
}

/**
 * @var int
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @var string username
 *
 * @ORM\Column(type="string", length=64, nullable=true)
 */
protected $username;

/**
 * @var string targetedId
 *
 * @ORM\Column(type="string", length=64, nullable=true, name="targeted_id")
 */
protected $targetedID;

/**
 * @var string
 * @ORM\Column(type="string", length=32, name="provider_id", nullable=true)
 */
protected $providerID;

/**
 * @var string
 * @ORM\Column(type="string", length=32, name="auth_svc_name")
 */
protected $authenticationServiceName;

/**
 * @var string
 * @ORM\Column(type="string", length=64, name="session_index", nullable=true)
 */
protected $sessionIndex;

/**
 * @var string
 * @ORM\Column(type="string", length=64, name="name_id")
 */
protected $nameID;

/**
 * @var string
 * @ORM\Column(type="string", length=64, name="name_id_format")
 */
protected $nameIDFormat;

/**
 * @var \DateTime
 * @ORM\Column(type="datetime", name="created_on")
 */
protected $createdOn;

/**
 * @var UserData
 * @ORM\OneToOne(targetEntity="UserData", cascade={"all"}, fetch="EAGER")
 * @ORM\JoinColumn(name="user_data", referencedColumnName="id")
 */
protected $userData;

Добавьте свой класс в файл config.yml (Шаг 4):

# app/config/config.yml
aerial_ship_saml_sp:
    driver: orm
    sso_state_entity_class: SamlBundle\Entity\SamlUser

Обновите файл security.yml (Шаг 5). Пример;

providers:
    saml_user_provider:
        id: SamlToState

firewalls:
    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false

    saml:
        pattern: ^/(?!login_check)
        anonymous: true
        aerial_ship_saml_sp:
            login_path: /saml/sp/login
            check_path: /saml/sp/acs
            logout_path: /saml/sp/logout
            failure_path: /saml/sp/failure
            metadata_path: /saml/sp/FederationMetadata.xml
            discovery_path: /saml/sp/discovery
            local_logout_path: /logout
            provider: saml_user_provider
            create_user_if_not_exists: true
            services:
                openidp:
                    idp:
                        #the XML-File you saved from the IDP earlier
                        file: "@SamlBundle/Resources/idp-FederationMetadata.xml"
                    sp:
                        config:
                            # required, has to match entity id from IDP XML
                            entity_id: http://your-idp-domain.com
                            # if different then url being used in request
                            # used for construction of assertion consumer and logout urls in SP entity descriptor
                            base_url: http://your-sp-domain.com
                        signing:
                             #self signed certificate, see [SamlSPBundle docs][4]
                            cert_file: "@SamlBundle/Resources/saml.crt"
                            key_file: "@SamlBundle/Resources/saml.pem"
                            key_pass: ""
                        meta:
                            # must implement SpMetaProviderInterface
                            # id: my.sp.provider.service.id

                            # or use builtin SpMetaConfigProvider
                            # any valid saml name id format or shortcuts: persistent or transient
                            name_id_format: transient
                            binding:
                                # any saml binding or shortcuts: post or redirect
                                authn_request: redirect
                                logout_request: redirect
        logout:
            path:   /logout
            target: /
            invalidate_session: true

Затем импортируйте маршруты, как описано в Шаге 6. Прежде чем перейти к шагу 7, я рекомендую сначала создать класс поставщика услуг пользователя. Вот пример:

namespace SamlBundle\Models;

use SamlBundle\Entity\SamlUser;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use AerialShip\SamlSPBundle\Bridge\SamlSpInfo;
use AerialShip\SamlSPBundle\Security\Core\User\UserManagerInterface as UserManagerInterface;


class SamlToState implements UserManagerInterface
{
/**
 * @var ContainerInterface   base bundle container
 */
public $container;

/**
 * Constructor with DependencyInjection params.
 *
 * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
 */
public function __construct(ContainerInterface $container)  {
    $this->container = $container;
}

/**
 * {@inheritdoc}
 */
public function loadUserBySamlInfo(SamlSpInfo $samlInfo)
{
    $user = $this->loadUserByTargetedID($samlInfo->getAttributes()['eduPersonTargetedID']->getFirstValue());

    return $user;
}

private function loadUserByTargetedID($targetedID) {
    $repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');

    $user = $repository->findOneBy(
            array('targetedID' => $targetedID)
    );

    if ($user) {
        return $user;
    }

    throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException();
}

/**
 * {@inheritdoc}
 */
public function createUserFromSamlInfo(SamlSpInfo $samlInfo)
{
    $repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');

    $user = $repository->findOneBy(
            array('nameID' => $samlInfo->getNameID()->getValue())
    );

    if ($user) {
        $user->setUsername($samlInfo->getAttributes()['eduPersonPrincipalName']->getFirstValue());
        $user->setTargetedID($samlInfo->getAttributes()['eduPersonTargetedID']->getFirstValue());
        $user->setRoles($samlInfo->getAttributes()['role']->getFirstValue());
    } else {
        $user = new SamlUser();
        $user->setUsername($samlInfo->getAttributes()['eduPersonPrincipalName']->getFirstValue());
        $user->setTargetedID($samlInfo->getAttributes()['eduPersonTargetedID']->getFirstValue());
        $user->setRoles($samlInfo->getAttributes()['role']->getFirstValue());
        $user->setSessionIndex($samlInfo->getAuthnStatement()->getSessionIndex());

        $user->setProviderID($samlInfo->getNameID()->getSPProvidedID());
        $user->setAuthenticationServiceName($samlInfo->getAuthenticationServiceID());
        $user->setNameID($samlInfo->getNameID()->getValue());
        $user->setNameIDFormat($samlInfo->getNameID()->getFormat());
    }

    $em = $this->container->get('doctrine')->getManager();
    $em->persist($user);
    $em->flush();

    return $user;
}

public function loadUserByUsername($username)
{
    $repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');

    $user = $repository->findOneBy(
            array('username' => $username)
    );

    if ($user) {
        return $user;
    }

    throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException();
    return false;
}

/**
 * {@inheritdoc}
 */
public function refreshUser(UserInterface $user)
{
    $repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');

    $newUser = $repository->findOneBy(
            array('nameID' => $user->getNameID())
    );

    if (!$newUser) {
        throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException();
    }

    return $newUser;
}

/**
 * {@inheritdoc}
 */
public function supportsClass($class)
{
    return true;
}

}

Создайте свой сервис в SamlBundle/Resources/config/services.yml:

services:
    SamlToState:
        class: SamlBundle\Models\SamlToState
        arguments: [@service_container]

Теперь пришло время для Шаг 7, обмен метаданными. получите XML-файл SP, как описано, и вернитесь к своему IDP. Вы найдете ссылку "Конвертер метаданных XML в SimpleSAMLphp" на вкладке Федерация. Перейдите по этой ссылке и преобразуйте свои XML-данные SP в формат SimpleSAMLphp. Добавьте эти данные в saml20-sp-remote.php файл в папке метаданных ВПЛ.

Хорошо, я почти уверен, что что-то забыл, но, надеюсь, эта информация поможет. Если вы застрянете, пожалуйста, свяжитесь со мной.

 4
Author: Chris, 2018-09-30 06:16:13

Я нашел:

  1. SURFnet SamlBundle это простая оболочка symfony2 библиотеки, которую вы нашли.
  2. samlspbundle более используемый и хорошо документированный.

Взгляните на этих двоих. Первый очень прост, и я не знаю, достаточно ли документирован, конечно, это активный проект. Второй кажется более мощным и документированным, но его может быть сложнее настроить.

Надеюсь, это поможет

 1
Author: Matteo, 2015-02-15 15:11:07