اذهب إلى المحتوى

السؤال

Recommended Posts

  • 1
نشر

وعليكم السلام ورحمة الله وبركاته.

أولا يجب عليك إنشاء جدول في قاعدة البيانات ليحوي رمز إعادة تعين كلمة المرور . ولنقوم بتسمية الجدول بإسم password_resets وهذا هو إستعلام إنشاء الجدول :

CREATE TABLE password_resets (
    email VARCHAR(255) NOT NULL,
    token VARCHAR(255) NOT NULL,
    expires_at DATETIME NOT NULL
);

هنا في جدول نقوم بحفظ البريد الإلكتروني و ال token الخاص بإعادة التعين . وتاريخ الإنتهاء الخاص بالرمز token.

ولنقوم بإنشاء صفحة لطلب إعادة تعين كلمة المرور وليكن إسم الملف هو request_reset.php:

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $email = $_POST['email'];

    $pdo = new PDO("mysql:host=localhost;dbname=databasename", "username", "password");
    $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
    $stmt->execute([$email]);
    if ($stmt->rowCount() > 0) {
        $token = bin2hex(random_bytes(32));
        $expires = date("Y-m-d H:i:s", time() + 3600); // تاريخ الصلاحية هو ساعة واحدة

        // حذف أي رمز سابق موجود
        $pdo->prepare("DELETE FROM password_resets WHERE email = ?")->execute([$email]);

        $stmt = $pdo->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)");
        $stmt->execute([$email, $token, $expires]);

        // أرسل البريد الإلكتروني 
        $resetLink = "https://yourdomain.com/reset_password.php?token=$token";
        $mail = new PHPMailer(true);

        try {
            // إعدادات SMTP
            $mail->isSMTP();
            $mail->Host       = 'smtp.gmail.com';
            $mail->SMTPAuth   = true;
            $mail->Username   = 'your_email@gmail.com'; 
            $mail->Password   = 'your_app_password';    // كلمة مرور التطبيق
            $mail->SMTPSecure = 'tls';
            $mail->Port       = 587;

            // تفاصيل الرسالة
            $mail->setFrom('your_email@gmail.com', 'اسم الموقع');
            $mail->addAddress($email);
            $mail->Subject = 'إعادة تعيين كلمة المرور';
            $mail->Body    = "انقر على الرابط التالي لإعادة تعيين كلمة المرور:\n\n$resetLink\n\nالرابط صالح لمدة ساعة.";
            $mail->send();
            echo "تم إرسال رابط إعادة تعيين كلمة المرور إلى بريدك الإلكتروني.";
        } catch (Exception $e) {
            echo "حدث خطأ أثناء إرسال البريد: {$mail->ErrorInfo}";
        }
    } else {
        echo "البريد الإلكتروني غير مسجل.";
    }
}
?>
<form method="POST">
    البريد الإلكتروني: <input type="email" name="email" required>
    <button type="submit">إرسال الرابط</button>
</form>

ولكن يجب أولا مكتبة PHPMailer من خلال الأمر :

composer require phpmailer/phpmailer

وأيضا تأكد من وضع إعدادات ال smtp الخاصة بالبريد الذي ستقوم بإرسال الرسائل منه.

وأخيرا صفحة إعادة تعيين كلمة المرور reset_password.php :

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $token = $_POST['token'];
    $newPassword = $_POST['password'];

    $pdo = new PDO("mysql:host=localhost;dbname=yourdb", "username", "password");
    $stmt = $pdo->prepare("SELECT * FROM password_resets WHERE token = ? AND expires_at > NOW()");
    $stmt->execute([$token]);
    $reset = $stmt->fetch();

    if ($reset) {
        $hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare("UPDATE users SET password = ? WHERE email = ?");
        $stmt->execute([$hashedPassword, $reset['email']]);

        $pdo->prepare("DELETE FROM password_resets WHERE email = ?")->execute([$reset['email']]);

        echo "تم تغيير كلمة المرور بنجاح.";
    } else {
        echo "الرابط غير صحيح أو إنتهت صلاحيته.";
    }
} elseif (isset($_GET['token'])) {
    $token = $_GET['token'];
?>
    <form method="POST">
        <input type="hidden" name="token" value="<?= htmlspecialchars($token) ?>">
        كلمة المرور الجديدة: <input type="password" name="password" required>
        <button type="submit">إعادة التعيين</button>
    </form>
<?php
} else {
    echo "الرابط غير صحيح.";
}
?>

 

  • 1
نشر

الفكرة كالتالي، ستطلب من المستخدم إدخال بريده الإلكتروني المرتبط بالحساب ولو البريد الإلكتروني موجود في قاعدة البيانات، قم بإنشاء رمز وهو Token فريد ومؤقت ثم إرسال رابط إلى البريد الإلكتروني يحتوي على الرمز الفريد.

وعند النقر على الرابط، اسمح للمستخدم بتعيين كلمة مرور جديدة.

لذا قاعدة البيانات يجب أن تحتوي على جدول لتخزين الرموز المؤقتة associated مع المستخدم ووقت الانتهاء:

CREATE TABLE password_resets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    token VARCHAR(255) NOT NULL,
    expires_at DATETIME NOT NULL
);

ونموذج  طلب إعادة التعيين:

<form action="request_reset.php" method="POST">
    <input type="email" name="email" required placeholder="أدخل بريدك الإلكتروني">
    <button type="submit">استعادة كلمة المرور</button>
</form>

ثم تثبيت مكتبة PHPMailer:

composer require phpmailer/phpmailer

ثم إنشاء منطق وإرسال رمز إعادة التعيين من خلال ملف وليكن باسم request_reset.php:

<?php
require 'vendor/autoload.php'; 
require 'db.php'; 
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $email = filter_var($_POST["email"], FILTER_SANITIZE_EMAIL);

    $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
    $stmt->execute([$email]);
    if ($stmt->rowCount() > 0) {
        $token = bin2hex(random_bytes(32));
        $expires = date("Y-m-d H:i:s", strtotime('+1 hour'));
        $stmt = $pdo->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)");
        $stmt->execute([$email, $token, $expires]);

        $reset_link = "https://mustafa.com/reset_password.php?token=$token";

        $mail = new PHPMailer(true);
        try {
            $mail->isSMTP();
            $mail->Host = 'smtp.yourmailserver.com';
            $mail->SMTPAuth = true;
            $mail->Username = 'ضع الإيميل هنا@yourdomain.com';
            $mail->Password = 'الباسورد هنا'; 
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            $mail->Port = 587;

            $mail->setFrom('no-reply@yourdomain.com', 'Support');
            $mail->addAddress($email);

            $mail->isHTML(true);
            $mail->Subject = 'إعادة تعيين كلمة المرور';
            $mail->Body = "لقد طلبت إعادة تعيين كلمة المرور. اضغط على الرابط التالي:<br><a href='$reset_link'>$reset_link</a><br>إذا لم تطلب ذلك، تجاهل الرسالة.";

            $mail->send();
            echo "تم إرسال رابط استعادة كلمة المرور إلى بريدك الإلكتروني إذا كان موجودًا في النظام.";
        } catch (Exception $e) {
            echo "حدث خطأ أثناء إرسال البريد الإلكتروني.";
        }
    } else {
        echo "تم إرسال رابط استعادة كلمة المرور إلى بريدك الإلكتروني إذا كان موجودًا في النظام.";
    }
}
?>

ثم ملف إعادة تعيين كلمة المرور reset_password.php:

<?php
if (!isset($_GET['token'])) exit('رمز غير صالح!');

$token = $_GET['token'];

require 'db.php';
$stmt = $pdo->prepare("SELECT email FROM password_resets WHERE token = ? AND expires_at > NOW()");
$stmt->execute([$token]);
$user = $stmt->fetch();
if (!$user) exit('الرابط غير صالح أو انتهت صلاحيته!');

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $new_password = $_POST["password"];
  
    $hashed = password_hash($new_password, PASSWORD_DEFAULT);

    $stmt = $pdo->prepare("UPDATE users SET password = ? WHERE email = ?");
    $stmt->execute([$hashed, $user['email']]);

    $stmt = $pdo->prepare("DELETE FROM password_resets WHERE email = ?");
    $stmt->execute([$user['email']]);

    echo "تم تحديث كلمة المرور بنجاح!";
    exit;
}
?>

<form method="POST">
    <input type="password" name="password" required placeholder="كلمة المرور الجديدة">
    <button type="submit">إعادة تعيين كلمة المرور</button>
</form>

لاحظ password_hash وpassword_verify لحفظ والتحقق من كلمة المرور، والأفضل تحديد صلاحية رمز إعادة التعيين لمدة محدودة مثلاً ساعة واحدة، ولا يجب توضيح هل البريد متوفر أم لا في الاستجابة لتجنب هجمات التخمين.

أيضًا لمنع هجمات إعادة الإرسال، احذف الرمز بعد استخدامه مباشرة.

  • 0
نشر
بتاريخ 9 ساعة قال m_sh:

مرحبا مهندس مصطفى ، PHP فقط 

وعليكم السلام ورحمة الله وبركاته،

سأساعدك في كتابة كود آمن لاستعادة كلمة المرور باستخدام PHP ، مع التركيز على الأمان وأفضل الممارسات. الكود سيسمح للأعضاء بطلب رابط إعادة تعيين كلمة المرور عبر البريد الإلكتروني، مع استخدام رمز (token) مؤقت ومشفّر لضمان الأمان يجب إنشاء قاعدة بيانات تحتوي على جدول للأعضاء (مثال: users) وجدول لتخزين رموز إعادة التعيين (password_resets) و خادم بريد (SMTP) لإرسال البريد الإلكتروني (سنستخدم مكتبة PHPMailer) و تهيئة قاعدة البيانات وملفات الكود.

project/
	config.php               # إعدادات الاتصال بقاعدة البيانات
	forgot_password.php      # صفحة طلب إعادة تعيين كلمة المرور
	reset_password.php       # صفحة إدخال كلمة المرور الجديدة
	vendor/                 # مكتبة PHPMailer (يتم تثبيتها عبر Composer)
	database.sql            # هيكلية قاعدة البيانات

و جدول قاعدة البيانات تحتوي على 

-- جدول الأعضاء
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- جدول رموز إعادة تعيين كلمة المرور
CREATE TABLE password_resets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    token VARCHAR(255) NOT NULL,
    expires_at DATETIME NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (email) REFERENCES users(email)
);

وصفحةصفحة طلب إعادة تعيين كلمة المرور هي 

<?php
require 'config.php';
session_start();

$message = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);

    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $message = 'البريد الإلكتروني غير صالح.';
    } else {
        // التحقق من وجود البريد في قاعدة البيانات
        $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
        $stmt->execute([$email]);
        $user = $stmt->fetch();

        if ($user) {
            // إنشاء رمز (token) عشوائي
            $token = bin2hex(random_bytes(32));
            $expires_at = date('Y-m-d H:i:s', strtotime('+1 hour'));

            // تخزين الرمز في قاعدة البيانات
            $stmt = $pdo->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)");
            $stmt->execute([$email, $token, $expires_at]);

            // إعداد رابط إعادة التعيين
            $reset_link = "http://yourdomain.com/reset_password.php?email=" . urlencode($email) . "&token=" . $token;

            // إرسال البريد الإلكتروني باستخدام PHPMailer
            $mail = new PHPMailer(true);
            try {
                $mail->isSMTP();
                $mail->Host = SMTP_HOST;
                $mail->SMTPAuth = true;
                $mail->Username = SMTP_USER;
                $mail->Password = SMTP_PASS;
                $mail->SMTPSecure = SMTP_SECURE;
                $mail->Port = SMTP_PORT;

                $mail->setFrom(SMTP_USER, 'نظام إعادة تعيين كلمة المرور');
                $mail->addAddress($email);
                $mail->isHTML(true);
                $mail->Subject = 'إعادة تعيين كلمة المرور';
                $mail->Body = "مرحبًا،<br><br>لقد طلبت إعادة تعيين كلمة المرور. انقر على الرابط التالي لإعادة التعيين:<br><a href='$reset_link'>إعادة تعيين كلمة المرور</a><br><br>الرابط صالح لمدة ساعة واحدة فقط.<br>إذا لم تطلب هذا، يرجى تجاهل هذا البريد.";
                $mail->AltBody = "لقد طلبت إعادة تعيين كلمة المرور. انسخ الرابط التالي في متصفحك: $reset_link\nالرابط صالح لمدة ساعة واحدة.";

                $mail->send();
                $message = 'تم إرسال رابط إعادة التعيين إلى بريدك الإلكتروني.';
            } catch (Exception $e) {
                $message = 'فشل إرسال البريد: ' . $mail->ErrorInfo;
            }
        } else {
            $message = 'البريد الإلكتروني غير مسجل.';
        }
    }
}
?>

<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>استعادة كلمة المرور</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
        .message { padding: 10px; margin-bottom: 10px; border-radius: 5px; }
        .success { background-color: #d4edda; color: #155724; }
        .error { background-color: #f8d7da; color: #721c24; }
        input { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #ddd; border-radius: 5px; }
        button { padding: 10px 20px; background-color: #007bff; color: #fff; border: none; border-radius: 5px; cursor: pointer; }
        button:hover { background-color: #0056b3; }
    </style>
</head>
<body>
    <h2>استعادة كلمة المرور</h2>
    <?php if ($message): ?>
        <div class="message <?php echo strpos($message, 'تم') === 0 ? 'success' : 'error'; ?>">
            <?php echo htmlspecialchars($message); ?>
        </div>
    <?php endif; ?>
    <form method="POST" action="">
        <label for="email">البريد الإلكتروني:</label>
        <input type="email" id="email" name="email" required>
        <button type="submit">إرسال رابط إعادة التعيين</button>
    </form>
</body>
</html>

وصفحة إعادة تعيين كلمة المرور هي 

<?php
require 'config.php';
session_start();

$message = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);

    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $message = 'البريد الإلكتروني غير صالح.';
    } else {
        // التحقق من وجود البريد في قاعدة البيانات
        $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
        $stmt->execute([$email]);
        $user = $stmt->fetch();

        if ($user) {
            // إنشاء رمز (token) عشوائي
            $token = bin2hex(random_bytes(32));
            $expires_at = date('Y-m-d H:i:s', strtotime('+1 hour'));

            // تخزين الرمز في قاعدة البيانات
            $stmt = $pdo->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)");
            $stmt->execute([$email, $token, $expires_at]);

            // إعداد رابط إعادة التعيين
            $reset_link = "http://yourdomain.com/reset_password.php?email=" . urlencode($email) . "&token=" . $token;

            // إرسال البريد الإلكتروني باستخدام PHPMailer
            $mail = new PHPMailer(true);
            try {
                $mail->isSMTP();
                $mail->Host = SMTP_HOST;
                $mail->SMTPAuth = true;
                $mail->Username = SMTP_USER;
                $mail->Password = SMTP_PASS;
                $mail->SMTPSecure = SMTP_SECURE;
                $mail->Port = SMTP_PORT;

                $mail->setFrom(SMTP_USER, 'نظام إعادة تعيين كلمة المرور');
                $mail->addAddress($email);
                $mail->isHTML(true);
                $mail->Subject = 'إعادة تعيين كلمة المرور';
                $mail->Body = "مرحبًا،<br><br>لقد طلبت إعادة تعيين كلمة المرور. انقر على الرابط التالي لإعادة التعيين:<br><a href='$reset_link'>إعادة تعيين كلمة المرور</a><br><br>الرابط صالح لمدة ساعة واحدة فقط.<br>إذا لم تطلب هذا، يرجى تجاهل هذا البريد.";
                $mail->AltBody = "لقد طلبت إعادة تعيين كلمة المرور. انسخ الرابط التالي في متصفحك: $reset_link\nالرابط صالح لمدة ساعة واحدة.";

                $mail->send();
                $message = 'تم إرسال رابط إعادة التعيين إلى بريدك الإلكتروني.';
            } catch (Exception $e) {
                $message = 'فشل إرسال البريد: ' . $mail->ErrorInfo;
            }
        } else {
            $message = 'البريد الإلكتروني غير مسجل.';
        }
    }
}
?>

<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>استعادة كلمة المرور</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
        .message { padding: 10px; margin-bottom: 10px; border-radius: 5px; }
        .success { background-color: #d4edda; color: #155724; }
        .error { background-color: #f8d7da; color: #721c24; }
        input { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #ddd; border-radius: 5px; }
        button { padding: 10px 20px; background-color: #007bff; color: #fff; border: none; border-radius: 5px; cursor: pointer; }
        button:hover { background-color: #0056b3; }
    </style>
</head>
<body>
    <h2>استعادة كلمة المرور</h2>
    <?php if ($message): ?>
        <div class="message <?php echo strpos($message, 'تم') === 0 ? 'success' : 'error'; ?>">
            <?php echo htmlspecialchars($message); ?>
        </div>
    <?php endif; ?>
    <form method="POST" action="">
        <label for="email">البريد الإلكتروني:</label>
        <input type="email" id="email" name="email" required>
        <button type="submit">إرسال رابط إعادة التعيين</button>
    </form>
</body>
</html>

ثم قم بتثبيت PHPMailer عبر Composer 

composer require phpmailer/phpmailer

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...