4

I'm transferring 10K users from Drupal 7 to Drupal 8. I want to retain passwords. What I'm trying is

  • Dump user records from Drupal 7 as a CSV file
  • Dump hashed passwords from MySQL as a CSV file
  • Load user records and hashed passwords into a custom program
  • In the program, add hashed passwords to the correct user records (match by UID)
  • Manipulate user records (consolidate duplicates, combine fields, and more)
  • output fixed-up user records (including password hash) to a CSV file
  • use this CSV file as input to a custom Drupal 8 module to create users

All of this is easy except creating users in Drupal 8 with their Drupal 7 passwords.

I have tried simply

$values = array
[
  'name' => 'test',
  'mail' => 'test@test.com',
  'roles' => [],
  'pass' => $hashed_drupal_7_password,
  'status' => 1,
];
$account = entity_create('user', $values);
$account->save();

but of course Drupal 8 assumes the pass value is the textual password and rehashes it.

Is there a way to get the already-hashed password into the user account, either during creation or after it is created? If I get them in, will they still work? As you can tell by reading, I'm a neophyte when it comes to passwords, encryption, etc. I've read many posts and articles, but don't recognize an answer to this question.

  • 2
    Does this answer your question? How do I migrate users passwords? – leymannx May 29 at 7:46
  • Thanks, @leymannx! This post does contain a very useful answer to my question. Not sure how I missed it. This said, the answer by MrD has a solution that is exactly what I was asking for. – Marshall Morrise May 29 at 13:42
  • 1
    I appreciate the helpful edits by @kiamlaluno, although in this case, it seems keeping "D7 to D8" in the title is useful, since the solutions proposed won't work for, say, D6 to D8 migration because hashing is different. – Marshall Morrise May 29 at 14:00
  • We don't put tags in the title, and those are. – kiamlaluno May 29 at 20:25
  • Got it. Thanks. What would be a good way to indicate this so readers could most easily see this is a D7 to D8 solution? – Marshall Morrise May 30 at 0:12
7

As @No Sssweat recommend, the D8 Migrate Modules is good way. With your way, you have to add property pre_hashed for field pass.

$values = [
  'name' => 'test',
  'mail' => 'test@test.com',
  'roles' => [],
  'pass' => [
    'value' => $hashed_drupal_7_password,
    'pre_hashed' => TRUE,
  ],
  'status' => 1,
];
$account = entity_create('user', $values);
$account->save();

You can find this property in FieldType Password

| improve this answer | |
  • Thanks very much, @MrD! I'll look into the migrate modules as suggested by others, but this is the cleanest, most direct answer to the question I asked, so I'm making it the accepted answer so others can find it. – Marshall Morrise May 29 at 13:55
6

You should use the D8 Migrate Modules to do this, specially for transferring 10K users, unless your current code is using the Batch API. Otherwise, you're going to run into timeouts because it's too big. Also, these migrate modules allow you to transfer from SQL to SQL. No need for CSV file, if you don't want. But you can still do CSV file import with them, if needed.


To answer your question programmatically, as far as I know, Drupal API doesn't offer a way to skip the hashing, probably for security reasons.

Since D7 and D8 use the same hashing, after User is created, you have to overwrite it by updating it manually/directly. Add this right after $account->save();.

// Updates user password
$uid = $account->id();
$query = \Drupal::database()->update('users_fields_data');
$query->fields([
  'pass' => $hashed_drupal_7_password,
]);
$query->condition('uid', $uid);
$query->execute();

Flush caches after.

Note: D6 uses different hashing, so this answer wouldn't work in that case.

| improve this answer | |
  • 3
    Don't the migration modules Drupal 8 has take care of the user accounts and their passwords too? The User module has the \Drupal\user\Plugin\migrate\source\d7\User class, which I take is for migration from a Drupal 7 site. (This answer is fine for programmatically doing that. I was just wondering if the OP should know there is already a core module for what he is trying to achieve.) – kiamlaluno May 29 at 7:33
  • Thanks for this very useful answer, @No Sssweat! I will look into the migrate modules to see if I can't use them instead of rolling my own, although I wonder if they'll give me the control I need, which includes looking across all user records to find and merge duplicates based on a varied set of criteria, before I add any users. The code you provide is great and cleaner than the code in drupal.stackexchange.com/questions/209163/…. This said, the answer by MrD is even cleaner, so I'll make it the accepted answer. – Marshall Morrise May 29 at 13:50
  • the answer by MrD is even cleaner, so I'll make it the accepted answer Completely agree. looking across all user records to find and merge duplicates based on a varied set of criteria It is possible, but this will require coding up a custom migrate plugin. Other alternative would be to do all the user clean up in D7 before migrating. – No Sssweat May 29 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.