如何获取D9注册提交的明文密码以同步用户至D7站点
方案1:拦截注册表单获取明文密码同步到D7
Drupal 9的hook_user_presave/hook_user_insert中拿到的密码已完成加密,因此需要在密码加密前拦截注册表单的提交数据:
- 通过
hook_form_alter修改用户注册表单,将自定义提交回调放在Drupal默认逻辑之前 - 在自定义回调中提取明文密码,调用D7的API完成用户同步
- 保留表单默认逻辑,完成D9侧的用户创建流程
示例代码:
/** * Implements hook_form_alter(). */ function mymodule_form_user_register_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { // 将自定义回调插入到默认提交队列的最前面 array_unshift($form['actions']['submit']['#submit'], 'mymodule_user_register_submit'); } /** * 自定义注册表单提交回调,获取明文密码并同步至D7 */ function mymodule_user_register_submit(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) { // 提取表单中的明文密码及用户信息 $plain_password = $form_state->getValue('pass'); $username = $form_state->getValue('name'); $email = $form_state->getValue('mail'); // 调用D7用户注册API(替换为你的实际API地址和验证方式) $d7_api_url = 'https://your-d7-site.com/api/user/register'; $sync_data = [ 'name' => $username, 'mail' => $email, 'pass' => $plain_password, // 添加其他需要同步的用户字段 ]; $http_client = \Drupal::httpClient(); try { $response = $http_client->post($d7_api_url, [ 'json' => $sync_data, 'headers' => ['Authorization' => 'Bearer YOUR_D7_API_TOKEN'], ]); \Drupal::logger('mymodule')->info('用户同步至D7成功:@username', ['@username' => $username]); } catch (\Exception $e) { \Drupal::logger('mymodule')->error('用户同步至D7失败:@message', ['@message' => $e->getMessage()]); // 可选:同步失败时阻止D9创建用户,或标记用户后续重试 // $form_state->setErrorByName('', '同步至遗留站点失败,请稍后重试'); } }
方案2:迁移D9加密密码到D7(兼容处理)
若不想处理明文密码,可让D7直接支持验证D9的密码哈希:
确认D7的密码哈希兼容性:
- Drupal 7从7.38版本开始,核心原生支持bcrypt哈希(需PHP >= 5.5.0)
- 若D7版本低于7.38,安装
password_compat模块,为PHP 5.3+提供bcrypt支持
直接迁移密码哈希:
- 将D9用户表
users_field_data中的pass字段值(bcrypt格式哈希,以$2y$开头)直接复制到D7的users表pass字段 - D7会自动识别bcrypt格式的哈希,使用对应逻辑处理登录验证
- 将D9用户表
批量迁移示例:
可编写Drush命令或自定义脚本批量同步,伪代码如下:
// 批量同步D9用户哈希密码到D7 $d9_users = \Drupal::entityTypeManager()->getStorage('user')->loadMultiple(); $http_client = \Drupal::httpClient(); $d7_api_token = 'YOUR_D7_API_TOKEN'; foreach ($d9_users as $user) { if ($user->id() == 1) continue; // 跳过管理员用户 $sync_data = [ 'uid' => $user->id(), // 可选:保持UID一致 'name' => $user->getAccountName(), 'mail' => $user->getEmail(), 'pass' => $user->getPassword(), // D9的加密哈希值 ]; try { $response = $http_client->post('https://your-d7-site.com/api/user/update', [ 'json' => $sync_data, 'headers' => ['Authorization' => "Bearer $d7_api_token"], ]); \Drupal::logger('mymodule')->info('用户密码哈希同步成功:@username', ['@username' => $user->getAccountName()]); } catch (\Exception $e) { \Drupal::logger('mymodule')->error('用户密码哈希同步失败:@message', ['@message' => $e->getMessage()]); } }
注意事项
- 调用D7 API时必须使用HTTPS,同时做好接口权限控制(如OAuth2或API令牌验证)
- 方案1中若API同步失败,建议使用队列模块实现异步重试,避免阻塞用户注册流程
- 方案2中若D7无法识别bcrypt哈希,检查PHP版本及D7核心/模块版本,确保bcrypt支持已启用
内容的提问来源于stack exchange,提问作者HigherLogic
相关产品推荐
相关产品推荐

