nbgrp / onelogin-saml-bundle
OneLogin SAML Symfony Bundle
Requires
- php: ^8.2
- onelogin/php-saml: ^4
- psr/log: ^1 || ^2 || ^3
- symfony/config: ^7
- symfony/dependency-injection: ^7
- symfony/deprecation-contracts: ^3
- symfony/event-dispatcher-contracts: ^3
- symfony/http-foundation: ^7
- symfony/http-kernel: ^7
- symfony/routing: ^7
- symfony/security-bundle: ^7
- symfony/security-core: ^7
- symfony/security-http: ^7
Requires (Dev)
- doctrine/orm: ^2.3 || ^3
- phpunit/phpunit: ^11.2
- symfony/event-dispatcher: ^7
- 2.0.x-dev
- v2.0.2
- v2.0.1
- v2.0.0
- 1.4.x-dev
- v1.4.0
- 1.3.x-dev
- v1.3.2
- v1.3.1
- v1.3.0
- 1.2.x-dev
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- 1.1.x-dev
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- 1.0.x-dev
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-dependabot/github_actions/codecov/codecov-action-4
- dev-dependabot/github_actions/actions/cache-4
This package is auto-updated.
Last update: 2024-09-01 22:25:12 UTC
README
概述
OneLogin SAML Symfony Bundle.
此包依赖于 Symfony 6 及更高版本。
对于旧版本的 Symfony,您可以使用 hslavich/oneloginsaml-bundle,该包以此包为基础。
兼容性
安装
composer require nbgrp/onelogin-saml-bundle
如果您使用 Symfony Flex,它将自动启用该包。否则,要启用该包,请在 config/bundles.php
中添加以下代码
return [ // ... Nbgrp\OneloginSamlBundle\NbgrpOneloginSamlBundle::class => ['all' => true], ];
配置
要配置该包,您需要在 config/packages/nbgrp_onelogin_saml.yaml
中添加配置。您可以使用任何配置格式(yaml、xml 或 php),但为了方便,本文件中将使用 yaml。
有关 OneLogin PHP SAML 设置的更多信息,请参阅 https://github.com/onelogin/php-saml#settings。
您可以在以下配置值中使用占位符
<request_scheme_and_host>
,它将被从Request
对象中替换为相应的值。
- onelogin_settings.sp.entityId
- onelogin_settings.sp.assertionConsumerService.url
- onelogin_settings.sp.singleLogoutService.url
- onelogin_settings.baseurl
如果您在负载均衡器或反向代理后面运行应用程序,请注意 可信代理设置。
nbgrp_onelogin_saml: onelogin_settings: default: # Mandatory SAML settings idp: entityId: 'https://id.example.com/saml2/idp/metadata.php' singleSignOnService: url: 'https://id.example.com/saml2/idp/SSOService.php' binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect' singleLogoutService: url: 'https://id.example.com/saml2/idp/SingleLogoutService.php' binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect' x509cert: 'MIIC...' sp: entityId: 'https://myapp.com/saml/metadata' # Default: '<request_scheme_and_host>/saml/metadata' assertionConsumerService: url: 'https://myapp.com/saml/acs' # Default: '<request_scheme_and_host>/saml/acs' binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' singleLogoutService: url: 'https://myapp.com/saml/logout' # Default: '<request_scheme_and_host>/saml/logout' binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect' privateKey: 'MIIE...' # Optional SAML settings baseurl: 'https://myapp.com/saml/' # Default: '<request_scheme_and_host>/saml/' strict: true debug: true security: nameIdEncrypted: false authnRequestsSigned: false logoutRequestSigned: false logoutResponseSigned: false signMetadata: false wantMessagesSigned: false wantAssertionsEncrypted: false wantAssertionsSigned: true wantNameId: false wantNameIdEncrypted: false requestedAuthnContext: true requestedAuthnContextComparison: 'exact' wantXMLValidation: false relaxDestinationValidation: false destinationStrictlyMatches: true allowRepeatAttributeName: false rejectUnsolicitedResponsesWithInResponseTo: false signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' encryption_algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc' lowercaseUrlencoding: false contactPerson: technical: givenName: 'Tech User' emailAddress: 'techuser@example.com' support: givenName: 'Support User' emailAddress: 'supportuser@example.com' administrative: givenName: 'Administrative User' emailAddress: 'administrativeuser@example.com' organization: en-US: name: 'Example' displayname: 'Example' url: 'http://example.com' compress: requests: false responses: false # Optional another one SAML settings (see Multiple IdP below) another: idp: # ... sp: # ... # ... # Optional parameters use_proxy_vars: true idp_parameter_name: 'custom-idp' entity_manager_name: 'custom-em'
对于 idp
和 sp
部分,还有一些额外的参数。您可以从 OneLogin PHP SAML 文档中了解更多信息。
除了指定 IdP 和 SP 的 x509 证书和私钥之外,您还可以将它们存储在 OneLogin PHP SAML 的 certs 目录 中,或使用全局常量 ONELOGIN_CUSTOMPATH
来指定自定义目录(完整路径将为 ONELOGIN_CUSTOMPATH.'certs/'
)。
如果您不想设置某些联系人或组织信息,请不要添加这些参数,而是保留为空白。
在 config/packages/security.yaml
中配置用户提供者和防火墙
security: # ... providers: saml_provider: ## Basic provider instantiates a user with identifier and default roles saml: user_class: 'App\Entity\User' default_roles: ['ROLE_USER'] firewalls: main: pattern: ^/ saml: ## Match SAML attribute 'uid' with user identifier. ## Otherwise, used \OneLogin\Saml2\Auth::getNameId() method by default. identifier_attribute: uid ## Use the attribute's friendlyName instead of the name. use_attribute_friendly_name: true check_path: saml_acs login_path: saml_login logout: path: saml_logout access_control: - { path: ^/saml/(metadata|login|acs), roles: PUBLIC_ACCESS } - { path: ^/, roles: ROLE_USER }
编辑您的 config/routes.yaml
nbgrp_saml: resource: "@NbgrpOneloginSamlBundle/Resources/config/routes.php"
多个 IdP
您可以为多个 IdP 配置多个 OneLogin PHP SAML 设置。为此,您需要为每个 IdP 指定 SAML 设置(配置中具有 default
和 another
键的部分)并通过查询字符串参数 idp
或同名请求属性传递必要的 IdP 名称。您可以使用 idp_parameter_name
包参数使用其他名称。
要使用适当的 SAML 设置,所有对包路由的请求都必须包含正确的 IdP 参数。
如果请求没有包含 IdP 值的查询参数或属性,则将使用 onelogin_settings
部分中的第一个键作为默认 IdP。
使用反向代理
当您在反向代理后面使用您的应用程序并使用 X-Forwarded-*
头时,您需要设置参数 nbgrp_onelogin_saml.use_proxy_vars = true
,以允许底层的 OneLogin 库正确确定请求协议、主机和端口。
可选功能
将 SAML 属性注入到 User 对象中
要能够将 SAML 属性注入到用户对象中,您必须实现 SamlUserInterface
。
<?php namespace App\Entity; use Nbgrp\OneloginSamlBundle\Security\User\SamlUserInterface; class User implements SamlUserInterface { private $username; private $email; // ... public function setSamlAttributes(array $attributes) { $this->email = $attributes['mail'][0]; } }
除了将 SAML 属性注入到用户之外,您还可以通过当前安全令牌(应为
Nbgrp\OneloginSamlBundle\Security\Http\Authenticator\Token\SamlToken
的实例)的getAttributes
方法获取它们。
与经典登录表单集成
您可以通过编辑您的 security.yaml
来将 SAML 验证与传统的登录表单集成。
security: enable_authenticator_manager: true providers: user_provider: # ... firewalls: main: saml: # ... ## Traditional login form form_login: login_path: /login check_path: /login_check # ... logout: path: saml_logout
然后您可以在登录页面中添加指向路由 saml_login
的链接,以启动 SAML 登录。
<a href="{{ path('saml_login') }}">SAML Login</a>
如果您使用多个 IdP,您应通过 path
参数指定它。
<a href="{{ path('saml_login', { idp: 'another' }) }}">SAML Login</a>
即时用户配置
为了对用户进行配置,您必须使用会抛出
UserNotFoundException
的用户提供者(例如,在上面的示例中使用的EntityUserProvider
)。SamlUserProvider
不会抛出此异常,这将导致返回一个空的用户(如果您的用户类没有实现Nbgrp\OneloginSamlBundle\Security\User\SamlUserInterface
)。
当用户提供者找不到用户时,可以根据接收到的 SAML 属性创建新的用户配置。
通过编辑 services.yaml
创建用户工厂服务。
services: saml_user_factory: class: Nbgrp\OneloginSamlBundle\Security\User\SamlUserFactory arguments: ## User class - App\Entity\User ## Attribute mapping - password: 'notused' email: $mail name: $cn lastname: $sn roles: ['ROLE_USER'] groups: $groups[]
将值以 '$' 开头的映射项引用到 SAML 属性值。
以 '[]' 结尾的值将作为数组呈现(即使它们最初是标量)。
然后,将创建的服务 ID 作为 user_factory
参数添加到您的防火墙设置中的 security.yaml
。
security: # ... providers: saml_provider: ## Loads user from user repository entity: class: App\Entity\User property: username firewalls: main: provider: saml_provider saml: identifier_attribute: uid ## User factory service user_factory: saml_user_factory # ...
此外,您还可以创建自己的 User Factory,该工厂实现 Nbgrp\OneloginSamlBundle\Security\User\SamlUserFactoryInterface
。
<?php namespace App\Security; use App\Entity\User; use Nbgrp\OneloginSamlBundle\Security\User\SamlUserFactoryInterface; use Symfony\Component\Security\Core\User\UserInterface; class UserFactory implements SamlUserFactoryInterface { public function createUser(string $identifier, array $attributes): UserInterface { $user = new User(); $user->setRoles(['ROLE_USER']); $user->setUsername($username); $user->setEmail($attributes['mail'][0]); // ... return $user; } }
并将其添加到 services.yaml
。
services: saml_user_factory: class: App\Security\UserFactory
在创建时持久化用户和注入 SAML 属性
需要 Symfony EventDispatcher 组件和 Doctrine ORM。
如果您想在成功认证后持久化用户对象,您需要在 security.yaml
的防火墙设置中添加 persist_user
。
security: # ... firewalls: # ... main: saml: # ... persist_user: true
要使用非默认实体管理器,请在 nbgrp_onelogin_saml.entity_manager_name
包配置参数中指定其名称。
用户持久化是通过事件监听器 Nbgrp\OneloginSamlBundle\EventListener\User\UserCreatedListener
和 Nbgrp\OneloginSamlBundle\EventListener\User\UserModifiedListener
实现的,您可以根据需要对其进行装饰以覆盖默认行为。
此外,您还可以为 Nbgrp\OneloginSamlBundle\Event\UserCreatedEvent
和 Nbgrp\OneloginSamlBundle\Event\UserModifiedEvent
事件创建自己的监听器。
<?php namespace App\Security; use Nbgrp\OneloginSamlBundle\Event\UserCreatedEvent; use Symfony\Component\EventDispatcher\Attribute\AsEventListener; #[AsEventListener(event: UserCreatedEvent::class, dispatcher: 'security.event_dispatcher.main')] class UserCreatedListener { public function __invoke(UserCreatedEvent $event): void { // ... } }
重要:您必须指定触发事件的防火墙对应的 dispatcher
选项(在上面的示例中为 main
)。有关更多信息,请参阅 Security Events。