nordeus / crowd-user-bundle
CrowdUserBundle 是一个用于从 Atlassian Crowd 获取用户并进行验证的 Symfony 扩展包。
Requires
- php: ^7.0
- php-curl-class/php-curl-class: ^6.0
- sensio/framework-extra-bundle: ^5.0
- symfony/framework-bundle: ^3.4||^4.0
- symfony/security-bundle: *
- symfony/twig-bundle: *
Requires (Dev)
- phpunit/phpunit: ^6.0
This package is auto-updated.
Last update: 2024-09-20 20:05:51 UTC
README
CrowdUserBundle 是一个用于从 Atlassian Crowd 获取用户并进行验证的 Symfony 扩展包。
安装和配置
1. 使用 composer 克隆此仓库
在项目根目录执行以下操作
composer require nordeus/crowd-user-bundle
如果您使用 Symfony Flex
该扩展包已为您自动注册和配置!跳到步骤 4。
2. 在内核中启用扩展包
<?php
// config/bundles.php
return [
// ...
Nordeus\CrowdUserBundle\NordeusCrowdUserBundle::class => ['all' => true],
];
3. 导入 CrowdUserBundle 路由文件
# config/routes/nordeus_crowd_user.yaml
nordeus_crowd_user:
resource: "@NordeusCrowdUserBundle/Resources/config/routing.yaml"
如果您打算手动覆盖一些 CrowdUserBundle 的路由(见步骤 6),请确保在您的扩展包配置之后包含此文件。
4. 配置参数
以下是需要设置的参数
# config/packages/nordeus_crowd_user.yaml
nordeus_crowd_user:
crowd_application_name: crowd_application_name
crowd_application_password: crowd_application_password
crowd_service_url: http://crowd.your_domain.com:8095
sso_cookie_domain: your_domain.com
roles_to_groups:
ROLE_USER: [ users ]
ROLE_ADMIN: [ admins, superadmins ]
通过提供每个 Symfony 角色的 Crowd 组列表来设置您的 roles_to_groups 映射,以便那些组中的用户应该接收这些角色。
还有可选参数,它们有默认值。这些参数包括
# config/packages/nordeus_crowd_user.yaml
nordeus_crowd_user:
# ...
user_class: Nordeus\CrowdUserBundle\Security\User\CrowdUser
sso_cookie_name: crowd.token_key
service_uri: /crowd/rest/usermanagement/1/
curl_timeout: 2
connection_retries: 2
user_refresh_time: 600 # seconds
如果您想扩展 CrowdUser,请使用 user_class 参数并设置您的用户类名称作为值。
5. 配置您应用程序的安全性
# config/packages/security.yaml
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
providers:
crowd_provider:
id: crowd.user_provider
firewalls:
main:
pattern: ^/
crowd_form_login:
login_path: nordeus_crowd_user_login
check_path: nordeus_crowd_user_login_check
default_target_path: /
crowd_sso: true
logout:
path: nordeus_crowd_user_logout
anonymous: ~
access_denied_handler: crowd.access_denied_handler
access_control:
- { path: ^/(_(profiler|wdt)|img|css|js|login), role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, role: ROLE_USER }
default_target_path 键是可选的,可以重新配置,它是在成功登录后用户将被重定向的路径。
access_denied_handler 键是可选的,它将导致 拒绝访问 错误重定向到带有错误消息的登录页面,而不是中断请求。
6. (可选)覆盖一些 CrowdUserBundle 的功能
假设您想覆盖控制器(更改一些业务逻辑)或资源(模板、路由等)来自 CrowdUserBundle。有两种可能的方案
A. 扩展包继承
设置后,您的扩展包中任何匹配的文件将自动覆盖 CrowdUserBundle 中的文件。请阅读设置扩展包继承的基础知识并遵循此处的说明。
B. 手动重新路由
在您的扩展包中,定义一个使用现有 CrowdUserBundle 路径的路由,只需将其目标设置为您的某个操作即可。如果您需要原始功能的一些部分,请扩展原始控制器/模板。
7. 清除 Symfony 缓存
php bin/console cache:clear
待办事项
- 在测试环境中模拟或禁用身份验证
说明
Symfony 身份验证基于以下概念
在安全部分(app/config/security.yaml)中,您必须定义一个防火墙。最常见的情况是只定义一个防火墙 - main 防火墙。以下是一个示例
# app/config/security.yaml
security:
firewalls:
main:
pattern: ^/
crowd_form_login:
login_path: nordeus_crowd_user_login
check_path: nordeus_crowd_user_login_check
default_target_path: /
crowd_sso: true
logout:
path: nordeus_crowd_user_logout
anonymous: ~
access_denied_handler: crowd.access_denied_handler
防火墙实现的工作方式如下:防火墙监听 onKernelRequest 事件。当事件被触发时,它使用防火墙映射来确定将使用哪个防火墙来处理事件。防火墙映射返回一个与请求路径匹配的模式。在我们的情况下,我们只定义了一个防火墙,它匹配每个路径(“pattern: ^/”),因此我们的 main 防火墙负责在每个请求上验证用户。
main 防火墙有许多身份验证监听器,可以验证用户。因此,在内核请求时,它会遍历所有监听器,传递一个事件对象给它们的 handle 方法。如果有任何监听器返回一个 Response,它将中断循环并返回该响应。让我们列出这些监听器。
- Channel Listener
- 负责切换 HTTP 协议
- Context Listener
- 检查是否存在会话,如果会话中存在认证令牌(如果会话中存在认证令牌),则从会话中获取认证令牌
- 从认证令牌中获取用户,然后通过调用UserProvider的refreshUser方法刷新用户;之后将用户保存到认证令牌中,并将令牌存储在上下文中。
- 监听onKernelResponse事件 - 目的是在上下文中获取最终的认证令牌(如果它仍然存在)并将其存储回会话。
- “自定义监听器” - 将在后面解释,那些是
- pre_auth 监听器
- form 监听器
- http 监听器
- remember-me 监听器
- 注销监听器 - 如果在配置中启用,则为活动状态("logout: " ... )
- 检查是否请求了注销路径。如果是,调用其注销处理器(可能删除一些Cookie),将上下文设置为null,并将响应返回给防火墙,防火墙中断进一步认证。
- 匿名监听器 - 仅当在配置中启用时才活动 ("anonymous: ~")
- 此时,监听器有机会生成一个认证令牌。
- 如果没有人这样做(上下文中设置为null),则生成匿名令牌并将其设置在上下文中。
- 访问监听器
- 检查令牌是否存在于上下文中(如果匿名监听器不活动,可能被设置为null)
- 检查令牌是否已认证,如果没有,则尝试通过将令牌传递给AuthenticationManager来认证令牌。
“自定义监听器”是其他认证监听器可以附加的地方。在此实现中,有两个监听器:CrowdLoginAuthenticationListener和CrowdSSOAuthenticationListener。注册认证监听器的过程是通过实现SecurityFactoryInterface的工厂完成的(DependencyInjection/Security/Factory)。此接口表示您必须定义
- 位置,其中监听器将被放置在“自定义监听器”部分,它可以是以下值之一:pre_auth、form、http和remember-me。
- key,用于识别您的工厂。在配置(上面)中,我们通过在防火墙部分中列出它们来启用这些工厂(crowd_form_login和crowd-sso)。
- create方法,它应该创建入口点、认证监听器和认证提供者。
- addConfiguration用于定义工厂使用的参数。在上面的示例中,crowd_form_login工厂使用login_path和check_path。
现在,我们已经将监听器附加到防火墙,认证流程如下:认证监听器应从请求中获取一些数据(登录监听器从登录表单中获取用户名和密码,SSO监听器获取SSOCookieToken),然后监听器创建CrowdAuthenticationToken并用数据填充它,监听器调用令牌的认证。CrowdAuthenticationProvider接收认证令牌,从UserProvider中获取CrowdUser(使用认证令牌中提供的数据),将CrowdUser存储在认证令牌中。监听器再次获取认证令牌,然后将其标记为已认证并存储在上下文中。
登录是如何完成的:Symfony已经提供了AbstractAuthenticationListener,CrowdLoginAuthenticationListener扩展了它。AbstractAuthenticationListener执行一些检查(例如,检查请求的路径是否是登录页面的路径),然后调用CrowdLoginAuthenticationListener中的attemptAuthentication方法。该方法应返回CrowdAuthenticationProvider提供的CrowdAuthenticatedToken,然后AbstractAuthenticationListener调用SuccessHandler。因此,CrowdLoginAuthenticationListener获取用户名和密码,将它们发送到CrowdAuthenticationToken;CrowdLoginSuccessHandler在响应中设置一个SSO Crowd cookie;
现在,当用户登录时,认证令牌将存储在会话中。在每次请求中,登录监听器不做任何事情,除非请求路径与登录路径匹配。SSO监听器读取SSO Crowd cookie,因为会话中已存在认证令牌,所以它会在令牌上设置认证标志并返回它,无需在每次请求时从Crowd服务器获取用户。匿名监听器在上下文中找到认证令牌并不做任何事情。访问监听器检查认证令牌是否已认证——如果是,就完成了。用户保持认证状态。
如上所述,ContextListener在每次请求都会调用UserProvider的refreshUser方法,这就不必在每次请求时从Crowd获取用户,UserProvider仅在定义的参数“某些时间”后刷新用户。
如果用户请求注销,注销监听器激活,遍历所有的注销处理程序并调用它们的注销方法。CrowdSSOLogoutHandler删除SSO Crowd cookie。