PHP 支付密码校验

wen PHP项目 3

本文目录导读:

PHP 支付密码校验

  1. 基础支付密码校验类
  2. 支付密码验证与加密
  3. 前端密码强度即时检查
  4. 完整的支付密码校验函数

我来为您提供一个完整的PHP支付密码校验解决方案,包含多种校验方式和安全措施。

基础支付密码校验类

<?php
class PaymentPasswordValidator {
    // 密码最小长度
    const MIN_LENGTH = 6;
    // 密码最大长度
    const MAX_LENGTH = 20;
    // 常见弱密码列表
    private static $weakPasswords = [
        '123456', '12345678', '123456789', '111111', 
        '000000', 'abc123', 'password', 'qwerty',
        'a123456', '123123', '666666', '888888'
    ];
    /**
     * 基础格式校验
     * @param string $password 支付密码
     * @return array ['valid' => bool, 'message' => string]
     */
    public static function basicCheck($password) {
        if (empty($password)) {
            return ['valid' => false, 'message' => '支付密码不能为空'];
        }
        // 检查长度
        if (strlen($password) < self::MIN_LENGTH) {
            return ['valid' => false, 'message' => '支付密码长度不能少于' . self::MIN_LENGTH . '位'];
        }
        if (strlen($password) > self::MAX_LENGTH) {
            return ['valid' => false, 'message' => '支付密码长度不能超过' . self::MAX_LENGTH . '位'];
        }
        // 检查是否为纯数字或字母数字组合
        if (!preg_match('/^(?=.*[a-zA-Z0-9])[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};\':"\\\\|,.<>\/?]+$/', $password)) {
            return ['valid' => false, 'message' => '支付密码包含非法字符'];
        }
        return ['valid' => true, 'message' => '校验通过'];
    }
    /**
     * 复杂度检查
     * @param string $password 支付密码
     * @return array
     */
    public static function complexityCheck($password) {
        $check = self::basicCheck($password);
        if (!$check['valid']) {
            return $check;
        }
        // 检查是否包含数字
        $hasNumber = preg_match('/[0-9]/', $password);
        // 检查是否包含字母
        $hasLetter = preg_match('/[a-zA-Z]/', $password);
        // 建议包含数字和字母
        if (!$hasNumber || !$hasLetter) {
            return ['valid' => false, 'message' => '支付密码必须包含数字和字母'];
        }
        // 检查是否包含大写字母
        $hasUppercase = preg_match('/[A-Z]/', $password);
        // 检查是否包含小写字母
        $hasLowercase = preg_match('/[a-z]/', $password);
        // 检查是否包含特殊字符
        $hasSpecial = preg_match('/[!@#$%^&*()_+\-=\[\]{};\':"\\\\|,.<>\/?]/', $password);
        $score = 0;
        if ($hasNumber) $score++;
        if ($hasLetter) $score++;
        if ($hasUppercase) $score++;
        if ($hasLowercase) $score++;
        if ($hasSpecial) $score++;
        $strength = '';
        if ($score <= 1) {
            $strength = '弱';
        } elseif ($score <= 3) {
            $strength = '中等';
        } else {
            $strength = '强';
        }
        return [
            'valid' => true, 
            'message' => '复杂度检查通过', 
            'strength' => $strength,
            'score' => $score
        ];
    }
    /**
     * 弱密码检查
     * @param string $password 支付密码
     * @return bool
     */
    public static function isWeakPassword($password) {
        // 检查是否在常见弱密码列表中
        if (in_array($password, self::$weakPasswords)) {
            return true;
        }
        // 检查是否为连续数字
        if (preg_match('/^(?:0123456789|1234567890|0987654321)$/', $password)) {
            return true;
        }
        // 检查是否为重复数字
        if (preg_match('/^(\d)\1{2,}$/', $password)) {
            return true;
        }
        // 检查是否包含连续数字
        for ($i = 0; $i < strlen($password) - 2; $i++) {
            $num1 = ord($password[$i]);
            $num2 = ord($password[$i + 1]);
            $num3 = ord($password[$i + 2]);
            if (($num2 - $num1 == 1 && $num3 - $num2 == 1) || 
                ($num1 - $num2 == 1 && $num2 - $num3 == 1)) {
                return true;
            }
        }
        // 检查是否为重复字符模式
        if (preg_match('/(.)\1{2,}/', $password)) {
            // 最多允许重复2次,超过则视为弱密码
            preg_match_all('/(.)\1{2,}/', $password, $matches);
            if (count($matches[0]) > 0) {
                return true;
            }
        }
        return false;
    }
    /**
     * 完整校验流程
     * @param string $password 支付密码
     * @param bool $strictMode 是否开启严格模式
     * @return array
     */
    public static function validate($password, $strictMode = true) {
        // 基础校验
        $basicCheck = self::basicCheck($password);
        if (!$basicCheck['valid']) {
            return $basicCheck;
        }
        // 弱密码检查
        if (self::isWeakPassword($password)) {
            return ['valid' => false, 'message' => '支付密码过于简单,请使用更复杂的密码'];
        }
        // 严格模式检查
        if ($strictMode) {
            $complexityCheck = self::complexityCheck($password);
            if (!$complexityCheck['valid']) {
                return $complexityCheck;
            }
        }
        return ['valid' => true, 'message' => '支付密码设置成功'];
    }
    /**
     * 密码强度评估(用于前端显示)
     * @param string $password 支付密码
     * @return array
     */
    public static function strengthAssessment($password) {
        $result = self::complexityCheck($password);
        return [
            'password' => $password,
            'strength' => $result['strength'] ?? '弱',
            'score' => $result['score'] ?? 0,
            'valid' => $result['valid'] ?? false,
            'message' => $result['message'] ?? '未知'
        ];
    }
}

支付密码验证与加密

<?php
class PaymentPasswordManager {
    // 加密密钥(应该从配置文件读取)
    private static $encryptionKey = 'your-secret-key-here';
    /**
     * 加密支付密码
     * @param string $password 原始密码
     * @return string 加密后的密码
     */
    public static function encrypt($password) {
        // 使用PHP内置的密码哈希函数
        return password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
    }
    /**
     * 验证支付密码
     * @param string $password 输入的密码
     * @param string $hash 存储的哈希值
     * @return bool
     */
    public static function verify($password, $hash) {
        return password_verify($password, $hash);
    }
    /**
     * 检查密码是否需要重新哈希
     * @param string $hash 存储的哈希值
     * @return bool
     */
    public static function needsRehash($hash) {
        return password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12]);
    }
    /**
     * 存储支付密码(应存储在数据库中)
     * @param int $userId 用户ID
     * @param string $password 支付密码
     * @return bool
     */
    public static function storePaymentPassword($userId, $password) {
        // 先进行校验
        $validation = PaymentPasswordValidator::validate($password);
        if (!$validation['valid']) {
            return false;
        }
        // 加密密码
        $hashedPassword = self::encrypt($password);
        // 在这里执行数据库存储
        // PDO 示例:
        /*
        $pdo = getDatabaseConnection();
        $stmt = $pdo->prepare("INSERT INTO payment_passwords (user_id, hash, created_at) VALUES (?, ?, NOW())");
        $result = $stmt->execute([$userId, $hashedPassword]);
        return $result;
        */
        // 模拟存储成功
        return true;
    }
    /**
     * 验证支付密码输入
     * @param int $userId 用户ID
     * @param string $password 输入的密码
     * @return array
     */
    public static function validatePaymentPassword($userId, $password) {
        // 从数据库获取存储的哈希值
        // 示例:$hash = getPasswordHashFromDatabase($userId);
        $hash = '$2y$12$YourStoredHashHere'; // 示例哈希
        if (self::verify($password, $hash)) {
            // 验证客户端IP、设备信息等(如果需要)
            return [
                'valid' => true,
                'message' => '支付密码验证成功'
            ];
        } else {
            return [
                'valid' => false,
                'message' => '支付密码错误'
            ];
        }
    }
    /**
     * 尝试次数限制(防暴力破解)
     * @param int $userId 用户ID
     * @return bool 是否允许尝试
     */
    public static function checkAttemptLimit($userId) {
        // 获取用户尝试次数
        $attemptCount = getAttemptCountFromRedis($userId);
        $lastAttemptTime = getLastAttemptTimeFromRedis($userId);
        // 如果超过5次尝试,锁定15分钟
        if ($attemptCount >= 5) {
            $lockTime = strtotime($lastAttemptTime) + 900; // 15分钟
            if (time() < $lockTime) {
                return false;
            } else {
                // 重置尝试次数
                resetAttemptCount($userId);
                return true;
            }
        }
        return true;
    }
}

前端密码强度即时检查

<?php
// 用于前端验证的API端点
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
    if ($_POST['action'] === 'validate_payment_password') {
        $password = $_POST['password'] ?? '';
        // 使用PaymentPasswordValidator进行校验
        $result = PaymentPasswordValidator::validate($password, false); // 非严格模式
        // 如果通过基础校验,进行强度评估
        if ($result['valid']) {
            $strength = PaymentPasswordValidator::strengthAssessment($password);
            echo json_encode($strength);
        } else {
            echo json_encode($result);
        }
    }
    if ($_POST['action'] === 'check_strength') {
        $password = $_POST['password'] ?? '';
        $strength = PaymentPasswordValidator::strengthAssessment($password);
        echo json_encode($strength);
    }
    exit;
}
?>
<!-- 前端HTML示例 -->
<!DOCTYPE html>
<html>
<head>支付密码设置</title>
    <style>
        .password-strength {
            display: block;
            height: 10px;
            margin-top: 10px;
            background-color: #eee;
        }
        .strength-bar {
            height: 100%;
            width: 0;
            transition: width 0.3s;
        }
        #strength-label {
            margin-top: 5px;
            font-size: 12px;
            color: #666;
        }
    </style>
</head>
<body>
    <form id="payment-password-form">
        <label for="password">支付密码:</label>
        <input type="password" id="password" name="password" 
               placeholder="请输入支付密码" autocomplete="new-password">
        <div class="password-strength">
            <div class="strength-bar" id="strength-bar"></div>
        </div>
        <div id="strength-label"></div>
        <div id="message"></div>
        <button type="submit" id="submit-btn">提交</button>
    </form>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
    $(document).ready(function() {
        $('#password').on('keyup', function() {
            var password = $(this).val();
            // 实时检查密码强度
            $.ajax({
                url: window.location.href,
                method: 'POST',
                data: {
                    action: 'check_strength',
                    password: password
                },
                success: function(response) {
                    var data = JSON.parse(response);
                    updateStrengthUI(data);
                }
            });
        });
        function updateStrengthUI(data) {
            var color, width, labelText;
            switch(data.strength) {
                case '强':
                    color = '#27ae60';
                    width = '100%';
                    labelText = '强';
                    break;
                case '中等':
                    color = '#f39c12';
                    width = '60%';
                    labelText = '中等';
                    break;
                default:
                    color = '#e74c3c';
                    width = '30%';
                    labelText = '弱';
                    break;
            }
            $('#strength-bar').css({
                'width': width,
                'background-color': color
            });
            $('#strength-label').text('密码强度:' + labelText);
            if (data.valid) {
                $('#submit-btn').prop('disabled', false);
                $('#message').text('密码设置有效').css('color', '#27ae60');
            } else {
                $('#submit-btn').prop('disabled', true);
                $('#message').text(data.message).css('color', '#e74c3c');
            }
        }
        // 表单提交
        $('#payment-password-form').on('submit', function(e) {
            e.preventDefault();
            var password = $('#password').val();
            $.ajax({
                url: window.location.href,
                method: 'POST',
                data: {
                    action: 'validate_payment_password',
                    password: password
                },
                success: function(response) {
                    var data = JSON.parse(response);
                    $('#message').text(data.message).css(
                        'color', data.valid ? '#27ae60' : '#e74c3c'
                    );
                }
            });
        });
    });
    </script>
</body>
</html>

完整的支付密码校验函数

<?php
/**
 * 完整的支付密码校验函数
 * @param string $password 支付密码
 * @param array $options 配置选项
 * @return array 校验结果
 */
function validatePaymentPassword($password, $options = []) {
    // 默认配置
    $defaultOptions = [
        'min_length' => 6,
        'max_length' => 20,
        'require_letter_and_number' => true,
        'check_weak_password' => true,
        'strict_mode' => false
    ];
    $options = array_merge($defaultOptions, $options);
    $errors = [];
    $warnings = [];
    // 1. 基础检查
    if (empty($password) || strlen($password) < 1) {
        $errors[] = '支付密码不能为空';
    }
    // 2. 长度检查
    $len = strlen($password);
    if ($len < $options['min_length']) {
        $errors[] = "支付密码长度不能少于{$options['min_length']}位";
    }
    if ($len > $options['max_length']) {
        $errors[] = "支付密码长度不能超过{$options['max_length']}位";
    }
    // 3. 字符类型检查
    $hasNumber = (bool) preg_match('/[0-9]/', $password);
    $hasLetter = (bool) preg_match('/[a-zA-Z]/', $password);
    $hasUpperCase = (bool) preg_match('/[A-Z]/', $password);
    $hasLowerCase = (bool) preg_match('/[a-z]/', $password);
    $hasSpecial = (bool) preg_match('/[!@#$%^&*()_+\-=\[\]{};\':"\\\\|,.<>\/?]/', $password);
    if ($options['require_letter_and_number'] && (!$hasNumber || !$hasLetter)) {
        $errors[] = '支付密码必须包含数字和字母';
    }
    if ($options['strict_mode'] && !$hasUpperCase) {
        $warnings[] = '建议包含大写字母';
    }
    if ($options['strict_mode'] && !$hasSpecial) {
        $warnings[] = '建议包含特殊字符';
    }
    // 4. 弱密码检查
    if ($options['check_weak_password']) {
        $weakPatterns = [
            '/^123456$/',          // 连续数字
            '/^654321$/',          // 倒序数字
            '/^111111$/',          // 重复数字
            '/^000000$/',
            '/^abcdef$/',          // 连续字母
            '/^a1b2c3$/'           // 简单模式
        ];
        foreach ($weakPatterns as $pattern) {
            if (preg_match($pattern, $password)) {
                $errors[] = '支付密码过于简单';
                break;
            }
        }
    }
    // 5. 相似检查(可选)
    if (isset($options['old_password']) && $password === $options['old_password']) {
        $errors[] = '新支付密码不能与当前支付密码相同';
    }
    // 6. 结果返回
    if (!empty($errors)) {
        return [
            'valid' => false,
            'errors' => $errors,
            'warnings' => $warnings,
            'message' => $errors[0]
        ];
    }
    return [
        'valid' => true,
        'errors' => [],
        'warnings' => $warnings,
        'message' => '校验通过'
    ];
}
// 使用示例
$password = 'Abc123456';
$result = validatePaymentPassword($password, ['strict_mode' => true]);
if ($result['valid']) {
    echo "支付密码有效:{$result['message']}";
    if (!empty($result['warnings'])) {
        echo "\n警告:" . implode("、", $result['warnings']);
    }
} else {
    echo "支付密码无效:{$result['message']}";
}

这套支付密码校验方案提供了:

  1. 基础格式校验 - 长度、字符类型
  2. 复杂度检查 - 数字、字母、特殊字符组合
  3. 弱密码检测 - 常见弱密码、连续模式
  4. 安全建议 - 大小写、特殊字符
  5. 前端实时反馈 - 密码强度显示
  6. 防暴力破解 - 尝试次数限制
  7. 安全存储 - 使用bcrypt加密

根据实际需求,可以选择适合的校验级别和方法。

抱歉,评论功能暂时关闭!