CodeIgniter加密使用问题:PHP7.2 mcrypt移除后登录失败求助
Hey there, let's work through this CodeIgniter encryption issue you're facing — it's super common when upgrading from older versions, especially with PHP dropping mcrypt support. Let's break down how to distinguish encrypted vs unencrypted passwords and fix that login error.
First, let's clarify why your old code isn't working:
- The old
encrypt->decode()relied on the mcrypt extension, which PHP 7.2+ removed entirely. - CodeIgniter's newer Encryption library uses OpenSSL (more secure) and has a different output format — it adds checksums and uses different encoding under the hood. You can't directly decrypt old mcrypt-encrypted passwords with the new library, which is why your login is failing.
To handle both encrypted and unencrypted passwords (plus old vs new encrypted formats), you have two reliable options:
- Add a database field: Create a tinyint field like
password_typewhere:0= unencrypted plaintext1= old mcrypt-encrypted2= new OpenSSL-encrypted (via CodeIgniter's Encryption library)
- Detect old format (less reliable): Old mcrypt-encrypted passwords in CodeIgniter are usually base64-encoded and have a consistent length. But this is riskier than using a dedicated field, as plaintext passwords could accidentally match that pattern.
Here's a revised login validation script that handles all cases, plus migrates old passwords to the new system automatically when users log in:
// Fetch user by username first $row = $this->your_user_model->get_user_by_username($username); if (!$row) { $this->session->set_flashdata('error', 'Invalid credentials'); redirect('login'); } $password_is_valid = false; // Check password based on its type switch ($row->password_type) { case 0: // Unencrypted plaintext: direct comparison $password_is_valid = ($row->password === $password); break; case 1: // Old mcrypt-encrypted password: use a compatible library to decrypt // We'll use phpseclib's MCrypt replacement (since mcrypt is gone) require_once APPPATH . 'libraries/phpseclib/Crypt/MCrypt.php'; $mcrypt = new \phpseclib\Crypt\MCrypt('rijndael-256', 'cbc'); $mcrypt->setKey($this->config->item('encryption_key')); // Match the old CodeIgniter encryption settings (adjust IV if needed) $mcrypt->setIV(substr($this->config->item('encryption_key'), 0, 32)); $decrypted_old_password = $mcrypt->decrypt(base64_decode($row->password)); $password_is_valid = ($decrypted_old_password === $password); // If valid, migrate to new encryption automatically if ($password_is_valid) { $new_encrypted_pass = $this->encryption->encrypt($password); $this->your_user_model->update_user_password($row->id, $new_encrypted_pass, 2); } break; case 2: // New CodeIgniter Encryption library: use built-in decrypt $decrypted_new_password = $this->encryption->decrypt($row->password); $password_is_valid = ($decrypted_new_password === $password); break; } // Final login check if ($row->accesso == 1 && $password_is_valid) { // Set user session and redirect to dashboard $this->session->set_userdata('logged_in', true); $this->session->set_userdata('user_id', $row->id); redirect('dashboard'); } else { $this->session->set_flashdata('error', 'Invalid credentials'); redirect('login'); }
A quick note: Encryption is reversible (you can get the plaintext back), which is less secure than password hashing (irreversible). If possible, migrate all passwords to use PHP's built-in password_hash() and password_verify():
- When a user registers or resets their password:
$hashed_password = password_hash($password, PASSWORD_DEFAULT); // Store $hashed_password in the database, set password_type to 3 - When logging in:
$password_is_valid = password_verify($password, $row->password);
This is the industry standard for password storage and avoids encryption-related issues entirely.
内容的提问来源于stack exchange,提问作者Phantom Moore

