Mysql
 sql >> база данни >  >> RDS >> Mysql

Регистрация на потребител и проверка на имейл PHP и MySQL

Вече написах публикация в блог за създаване на пълна потребителска система за регистрация и влизане с помощта на PHP и MySQL, но не включих проверка на имейл.

Този урок е малко като актуализация на предишния урок. Освен че може да се регистрира, да влезе и да излезе от акаунта си, на потребителя ще бъде изпратен имейл за потвърждение на имейл адреса му с връзка, върху която може да кликне и да бъде потвърден имейл адресът си.

В повечето приложения, които ще създадете, е важно да добавите функция за проверка на имейл поради много причини:може да искате да изпратите имейл по-късно до потребителя и да сте сигурни, че той ще го види; или потребителят може да забрави паролата си и да трябва да я нулира, а за да направим това, ще трябва да му изпратим по имейл връзка за нулиране на паролата; има много други причини, но разбирате смисъла.

В тази система, която изграждаме днес, потребителите, които не са потвърдили имейла си, няма да могат да извършват определени действия (ще използвам проста демонстрация, като например преглед на бутон. Само проверени потребители ще могат да видят този бутон).

За да започнете, създайте нов PHP проект с име verify-user и в тази папка създайте два файла:signup.php и login.php.

signup.php:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" />
  <link rel="stylesheet" href="main.css">
  <title>User verification system PHP</title>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-md-4 offset-md-4 form-wrapper auth">
        <h3 class="text-center form-title">Register</h3>
        <form action="signup.php" method="post">
          <div class="form-group">
            <label>Username</label>
            <input type="text" name="username" class="form-control form-control-lg" value="<?php echo $username; ?>">
          </div>
          <div class="form-group">
            <label>Email</label>
            <input type="text" name="email" class="form-control form-control-lg" value="<?php echo $email; ?>">
          </div>
          <div class="form-group">
            <label>Password</label>
            <input type="password" name="password" class="form-control form-control-lg">
          </div>
          <div class="form-group">
            <label>Password Confirm</label>
            <input type="password" name="passwordConf" class="form-control form-control-lg">
          </div>
          <div class="form-group">
            <button type="submit" name="signup-btn" class="btn btn-lg btn-block">Sign Up</button>
          </div>
        </form>
        <p>Already have an account? <a href="login.php">Login</a></p>
      </div>
    </div>
  </div>
</body>
</html>

Това е просто обикновен HTML/CSS файл. Единственото нещо, което си струва да се отбележи, е, че използваме Bootstrap 4 CSS рамка за стилизиране на нашата страница. Можете да използвате всяка друга рамка за стил по ваш избор или да напишете свой собствен CSS, ако желаете.

Веднага след Bootstrap CSS, ние включваме main.css файл за персонализиран стил. Нека създадем този файл сега. В основната папка на приложението създайте файл, наречен main.css.

main.css:

@import url('https://fonts.googleapis.com/css?family=Lora');
li { list-style-type: none; }
.form-wrapper {
  margin: 50px auto 50px;
  font-family: 'Lora', serif;
  font-size: 1.09em;
}
.form-wrapper.login { margin-top: 120px; }
.form-wrapper p { font-size: .8em; text-align: center; }
.form-control:focus { box-shadow: none; }
.form-wrapper {
  border: 1px solid #80CED7;
  border-radius: 5px;
  padding: 25px 15px 0px 15px;
}
.form-wrapper.auth .form-title { color: #007EA7; }
.home-wrapper button,
.form-wrapper.auth button {
  background: #007EA7;
  color: white;
}
.home-wrapper {
  margin-top: 150px;
  border-radius: 5px;
  padding: 10px;
  border: 1px solid #80CED7;
}

На първия ред на този файл импортираме и използваме някои Google Fonts, за да направим шрифтовете ни да изглеждат по-красиви.

Сега се обърнете към файла login.php и направете подобно нещо.

login.php:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" />
  <link rel="stylesheet" href="main.css">
  <title>User verification system PHP - Login</title>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-md-4 offset-md-4 form-wrapper auth login">
        <h3 class="text-center form-title">Login</h3>
        <form action="login.php" method="post">
          <div class="form-group">
            <label>Username or Email</label>
            <input type="text" name="username" class="form-control form-control-lg" value="<?php echo $username; ?>">
          </div>
          <div class="form-group">
            <label>Password</label>
            <input type="password" name="password" class="form-control form-control-lg">
          </div>
          <div class="form-group">
            <button type="submit" name="login-btn" class="btn btn-lg btn-block">Login</button>
          </div>
        </form>
        <p>Don't yet have an account? <a href="signup.php">Sign up</a></p>
      </div>
    </div>
  </div>
</body>
</html>

В браузъра си отидете на http://localhost/cwa/verify-user/signup.php и ще видите красива форма за регистрация (същата за влизане). Игнорирайте грешките в полетата за въвеждане, скоро ще ги поправим.

Засега нека настроим базата данни. Създайте база данни, наречена verify-user и в тази база данни създайте потребителска таблица с атрибути, както следва:

CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `username` varchar(100) NOT NULL,
 `email` varchar(100) NOT NULL,
 `verified` tinyint(1) NOT NULL DEFAULT '0',
 `token` varchar(255) DEFAULT NULL,
 `password` varchar(255) NOT NULL,
 PRIMARY KEY (`id`)
)

Нищо необичайно освен, може би, токена и проверените полета, които ще обясня след малко.

Сега започваме с действителната логика на регистрация. Обикновено обичам да се позовавам на логическата част на приложението си като контролери и това е, което ще направя тук. В основната папка на проекта създайте папка, наречена контролери и вътре контролери, създайте файл, наречен authController.php.

контролери/authController.php:

<?php
session_start();
$username = "";
$email = "";
$errors = [];

$conn = new mysqli('localhost', 'root', '', 'verify-user');

// SIGN UP USER
if (isset($_POST['signup-btn'])) {
    if (empty($_POST['username'])) {
        $errors['username'] = 'Username required';
    }
    if (empty($_POST['email'])) {
        $errors['email'] = 'Email required';
    }
    if (empty($_POST['password'])) {
        $errors['password'] = 'Password required';
    }
    if (isset($_POST['password']) && $_POST['password'] !== $_POST['passwordConf']) {
        $errors['passwordConf'] = 'The two passwords do not match';
    }

    $username = $_POST['username'];
    $email = $_POST['email'];
    $token = bin2hex(random_bytes(50)); // generate unique token
    $password = password_hash($_POST['password'], PASSWORD_DEFAULT); //encrypt password

    // Check if email already exists
    $sql = "SELECT * FROM users WHERE email='$email' LIMIT 1";
    $result = mysqli_query($conn, $sql);
    if (mysqli_num_rows($result) > 0) {
        $errors['email'] = "Email already exists";
    }

    if (count($errors) === 0) {
        $query = "INSERT INTO users SET username=?, email=?, token=?, password=?";
        $stmt = $conn->prepare($query);
        $stmt->bind_param('ssss', $username, $email, $token, $password);
        $result = $stmt->execute();

        if ($result) {
            $user_id = $stmt->insert_id;
            $stmt->close();

            // TO DO: send verification email to user
            // sendVerificationEmail($email, $token);

            $_SESSION['id'] = $user_id;
            $_SESSION['username'] = $username;
            $_SESSION['email'] = $email;
            $_SESSION['verified'] = false;
            $_SESSION['message'] = 'You are logged in!';
            $_SESSION['type'] = 'alert-success';
            header('location: index.php');
        } else {
            $_SESSION['error_msg'] = "Database error: Could not register user";
        }
    }
}

// LOGIN
if (isset($_POST['login-btn'])) {
    if (empty($_POST['username'])) {
        $errors['username'] = 'Username or email required';
    }
    if (empty($_POST['password'])) {
        $errors['password'] = 'Password required';
    }
    $username = $_POST['username'];
    $password = $_POST['password'];

    if (count($errors) === 0) {
        $query = "SELECT * FROM users WHERE username=? OR email=? LIMIT 1";
        $stmt = $conn->prepare($query);
        $stmt->bind_param('ss', $username, $password);

        if ($stmt->execute()) {
            $result = $stmt->get_result();
            $user = $result->fetch_assoc();
            if (password_verify($password, $user['password'])) { // if password matches
                $stmt->close();

                $_SESSION['id'] = $user['id'];
                $_SESSION['username'] = $user['username'];
                $_SESSION['email'] = $user['email'];
                $_SESSION['verified'] = $user['verified'];
                $_SESSION['message'] = 'You are logged in!';
                $_SESSION['type'] = 'alert-success';
                header('location: index.php');
                exit(0);
            } else { // if password does not match
                $errors['login_fail'] = "Wrong username / password";
            }
        } else {
            $_SESSION['message'] = "Database error. Login failed!";
            $_SESSION['type'] = "alert-danger";
        }
    }
}

Ако сте следвали предишните ми уроци, тогава нищо в този файл не трябва да е ново за вас. Но в името на начинаещите, ще направя някои обяснения.

Първото нещо е, че започваме сесията с помощта на session_start(), тъй като ще трябва да съхраняваме влезлият потребител в сесията. След като стартираме сесията, ние инициализираме променливите $username и $email, които използваме в нашите формуляри, както и масива $errors, който ще съдържа грешките при валидиране на формуляра.

След това се свързваме с базата данни. Следващите два оператора if, които следват, са съответно кодът, който се изпълнява, когато потребителят щракне върху бутоните за регистрация или вход. В случай на регистрация проверяваме дали всички задължителни полета са попълнени правилно и едва след това пристъпваме към запазване на потребителя в базата данни. Ние също така генерираме токен (уникален, произволен низ) и го запазваме с потребител като атрибут. Това ще се използва за потвърждаване на потребителския имейл. Повече за това по-късно.

Тъй като нашият файл authController.php е отговорен за регистрацията и влизането, трябва да го включим в най-горната част на страниците signup.php и login.php, защото там се изпращат данните от формуляра. Така:

signup.php и login.php (в самия връх):

<?php include 'controllers/authController.php' ?>

Ако има някакви съобщения за грешка в масива $errors, трябва да ги покажем във формуляра. За да направите това, добавете това if изявление във вашия формуляр директно под заглавието на формуляра както за страниците за регистрация, така и за вход.

<!-- form title -->
<h3 class="text-center form-title">Register</h3> <!-- or Login -->

<?php if (count($errors) > 0): ?>
  <div class="alert alert-danger">
    <?php foreach ($errors as $error): ?>
    <li>
      <?php echo $error; ?>
    </li>
    <?php endforeach;?>
  </div>
<?php endif;?>

Ако няма грешки, нашият скрипт ще продължи да запазва потребителя в базата данни. След като запазим потребителя в базата данни, ние го влизаме незабавно. В нашия случай влизането на потребител означава съхраняване на неговите данни в сесията и точно това направихме.

В този момент вече можете да се регистрирате и дори да влезете в потребител. Но след като влезете, ще бъдете пренасочени към страницата index.php, която не съществува. Скоро ще го създадем.

В authController.php ние съхраняваме променливи съобщение и тип в сесията, които да се показват веднага щом потребителят влезе. съобщението е действителният текст на съобщението, докато типът е стилизиращ клас Bootstrap, който ще форматира съобщението с подходящ цветове в зависимост от стойността на типа.

Това съобщение се показва, след като потребителят е влязъл и се показва във файла index.php. Нека създадем този файл сега в основната папка на нашия проект.

index.php:

<?php include 'controllers/authController.php'?>
<?php
// redirect user to login page if they're not logged in
if (empty($_SESSION['id'])) {
    header('location: login.php');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" />
  <link rel="stylesheet" href="main.css">
  <title>User verification system PHP</title>
</head>

<body>
  <div class="container">
    <div class="row">
      <div class="col-md-4 offset-md-4 home-wrapper">

        <!-- Display messages -->
        <?php if (isset($_SESSION['message'])): ?>
        <div class="alert <?php echo $_SESSION['type'] ?>">
          <?php
            echo $_SESSION['message'];
            unset($_SESSION['message']);
            unset($_SESSION['type']);
          ?>
        </div>
        <?php endif;?>

        <h4>Welcome, <?php echo $_SESSION['username']; ?></h4>
        <a href="logout.php" style="color: red">Logout</a>
        <?php if (!$_SESSION['verified']): ?>
          <div class="alert alert-warning alert-dismissible fade show" role="alert">
            You need to verify your email address!
            Sign into your email account and click
            on the verification link we just emailed you
            at
            <strong><?php echo $_SESSION['email']; ?></strong>
          </div>
        <?php else: ?>
          <button class="btn btn-lg btn-primary btn-block">I'm verified!!!</button>
        <?php endif;?>
      </div>
    </div>
  </div>
</body>
</html>

Тази страница е предназначена да бъде достъпна само за влезли потребители. Ето защо в горната част на файла пренасочваме потребителя към страницата за вход, ако не е влязъл. Някъде в центъра на страницата показваме съобщението. След показване на съобщението, ние премахваме настройката на съобщението и въвеждаме променливи, защото не искаме то да остане там на страницата дори след като потребителят опресни страницата.

И накрая, в центъра на страницата извършваме проверка, за да видим дали влезлият потребител е потвърдил имейл адреса си или не. Не забравяйте, че добавихме потвърдената променлива в сесията, когато влязохме в потребителя. Ако потребителят е потвърден, показваме „Аз съм потвърден!!!“ бутон, за да го видят. Ако не са потвърдени, ние им казваме за връзката за потвърждение, която изпратихме на имейл адреса им, и ги молим да кликнат върху тази връзка, за да потвърдят имейла си.

Потвърдете имейла

Във файла authController.php използвахме коментар, за да посочим къде ще изпратим имейла за потвърждение на потребителя, като извикаме sendVerificationEmail(). Отидете до файла authController.php и разкоментирайте извикването на функцията по следния начин:

// TO DO: send verification email to user
sendVerificationEmail($email, $token);

Ще дефинираме тази функция в друг файл и ще включим този файл в authController.php. В папката Controllers създайте файл с име sendEmails.php.

Преди да добавим какъвто и да е код в този файл, позволете ми да кажа малко за PHP SwiftMailer, популярната библиотека за изпращане на имейли в PHP, която ще използваме в този проект за изпращане на имейли от localhost.

SwiftMailer е популярна богата на функции библиотека за изпращане на имейли в PHP приложения.

За да използвате Swiftmailer, първо трябва да инсталирате Composer. След като инсталирате composer, отворете терминала или командния ред и отидете до главната папка на проекта и изпълнете следната команда, за да добавите библиотеката Swift Mailer с всичките й файлове към нашия проект:

composer require "swiftmailer/swiftmailer:^6.0"

Това създава папка на доставчик в корена на нашето приложение, съдържаща целия код (класове), необходими за изпращане на имейл и също така създава composer.json файл в корена на приложението, който изглежда така:

{
    "require": {
        "swiftmailer/swiftmailer": "^6.0"
    }
}

Сега отворете файла sendEmails.php, който създадохме по-рано и нека напишем функцията sendVerificationEmail():

<?php
require_once './vendor/autoload.php';

// Create the Transport
$transport = (new Swift_SmtpTransport('smtp.gmail.com', 465, 'ssl'))
    ->setUsername(SENDER_EMAIL)
    ->setPassword(SENDER_PASSWORD);

// Create the Mailer using your created Transport
$mailer = new Swift_Mailer($transport);

function sendVerificationEmail($userEmail, $token)
{
    global $mailer;
    $body = '<!DOCTYPE html>
    <html lang="en">

    <head>
      <meta charset="UTF-8">
      <title>Test mail</title>
      <style>
        .wrapper {
          padding: 20px;
          color: #444;
          font-size: 1.3em;
        }
        a {
          background: #592f80;
          text-decoration: none;
          padding: 8px 15px;
          border-radius: 5px;
          color: #fff;
        }
      </style>
    </head>

    <body>
      <div class="wrapper">
        <p>Thank you for signing up on our site. Please click on the link below to verify your account:.</p>
        <a href="http://localhost/cwa/verify-user/verify_email.php?token=' . $token . '">Verify Email!</a>
      </div>
    </body>

    </html>';

    // Create a message
    $message = (new Swift_Message('Verify your email'))
        ->setFrom(SENDER_EMAIL)
        ->setTo($userEmail)
        ->setBody($body, 'text/html');

    // Send the message
    $result = $mailer->send($message);

    if ($result > 0) {
        return true;
    } else {
        return false;
    }
}

Първото изявление изисква файла autoload.php в този файл. Този файл autoload.php автоматично ще включва всички класове от библиотеката на Swift Mailer в папката на доставчика, която използваме в този файл.

В този пример използваме Gmail. Така че можете да замените SENDER_EMAIL и SENDER_PASSWORD с вашия Gmail адрес и парола, които искате да използвате като имейл адрес на подателя. (Имейл адресът на получателя е този, изпратен чрез формуляра).

Обикновено, за да изпратите имейл до някого, трябва да влезете в акаунта си в Gmail, преди да съставите имейла и да изпратите. Това е същото нещо като библиотеката Swift Mailer. Така че, когато получателят ($userEmail) получи имейла, това е вашият Gmail адрес (SENDER_EMAIL), той ще види като изпращащия имейл.

Сега извикваме функцията sendVerificationEmail() в нашия authController.php файл, но дефинирахме функцията във файла sendEmails.php. Нека включим файла sendEmails.php в нашия authController.php, за да направим тази функция достъпна във файла. В горната част на authController.php, точно преди session_start(), добавете следния ред:

require_once 'sendEmails.php';

Това е всичко, от което се нуждаем, господа (и дами), за да изпратим имейл до нашия потребител с връзка за потвърждение на имейл. Но ние работим върху localhost и Gmail ще блокира всички опити за влизане от Swift Mailer, работещ на localhost.

Изпращане на имейл от localhost

Ако искате това да работи на localhost, ще трябва да конфигурирате акаунта си в Gmail да приема влизане от по-малко сигурни приложения. Разбира се, това може да създаде известна уязвимост във вашия акаунт в Gmail, но можете да го направите само за краткото време, през което трябва да тествате това приложение на localhost. След тестване можете да отмените настройката на вашия акаунт в Gmail. След като приложението ви бъде хоствано в интернет, ще работите. Правим това само защото сме на локален хост.

Можете да бъдете още по-предпазливи и да създадете друг акаунт в Gmail само за такива цели.

Затова влезте в своя Gmail от браузъра си, отидете на https://myaccount.google.com/security#connectedapps и променете стойността „Разрешаване на по-малко сигурни приложения“ на ON.

Можете да изключите това, след като приключите с тестването на проекта на localhost.

С това ще можете да изпратите имейл от localhost с връзка за потвърждение, след като потребителят се регистрира. Сега погледнете отново метода sendVerificationEmail() и ще забележите, че в тялото на имейла, който изпращаме до потребителя, токенът, който генерирахме за този конкретен потребител (токенът е уникален), е зададен като параметър на връзката така че когато потребителят щракне върху връзката в имейла, ще бъде насочен към нашето приложение на страница, наречена verify_email.php с този маркер в URL адреса. Като това:

<a href="http://localhost/cwa/verify-user/verify_email.php?token=0a150966418fa3a694bcb3ab8fcacd2063a096accc0ee33c3e8c863538ee825c0b52f2e1535d0e1377558c378ba5fc3106eb">Verify Email!</a>

Така че можем да получим този токен в нашия verify_email.php по следния начин (успокойте се, скоро ще създадем този verify_email.php): 

$token = $_GET['token'];

Вече можем да използваме този токен, за да извлечем потребителя, който има този конкретен токен (не забравяйте, че токенът е уникален) и ако получим този потребител, актуализираме неговия запис, променяйки проверения атрибут на true в базата данни. След това можем с гордост да кажем, че сме потвърдили имейл адреса на този потребител.

Нека създадем този файл verify_email.php в основната папка на нашия проект:

verify_email.php:

<?php
session_start();

$conn = new mysqli('localhost', 'root', '', 'verify-user');

if (isset($_GET['token'])) {
    $token = $_GET['token'];
    $sql = "SELECT * FROM users WHERE token='$token' LIMIT 1";
    $result = mysqli_query($conn, $sql);

    if (mysqli_num_rows($result) > 0) {
        $user = mysqli_fetch_assoc($result);
        $query = "UPDATE users SET verified=1 WHERE token='$token'";

        if (mysqli_query($conn, $query)) {
            $_SESSION['id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            $_SESSION['email'] = $user['email'];
            $_SESSION['verified'] = true;
            $_SESSION['message'] = "Your email address has been verified successfully";
            $_SESSION['type'] = 'alert-success';
            header('location: index.php');
            exit(0);
        }
    } else {
        echo "User not found!";
    }
} else {
    echo "No token provided!";
}

Обърнете внимание, че задаването на стойността на проверената стойност на 1 е същото като задаване на истината, тъй като в MySQL типът на базата данни Boolean се интерпретира като tinyint.

Сега, когато потребителят щракне върху връзката в имейла си и го отведе до тази страница, той актуализира проверения статус на този потребител до true, влиза го и го пренасочва към страницата index.php. В индексната страница, след като потвърдите потребителя, ще забележите, че предупредителното съобщение, което съветва потребителя да потвърди имейл адреса си, вече е изчезнало и на негово място имаме „Потвърден съм!!!“ бутон, който е видим само за проверени потребители.

Едно последно нещо, на страницата index.php след влизане на потребителя, има връзка за излизане, която сочи към файл logout.php, който трябва да изведе потребителя. Нека създадем този файл в корена на нашето приложение:

logout.php:

<?php
session_destroy();
unset($_SESSION['id']);
unset($_SESSION['username']);
unset($_SESSION['email']);
unset($_SESSION['verify']);
header("location: login.php");

Така че освен че може да се регистрира, да потвърди имейл, да влезе, потребителят вече може също да излезе.

Заключение

Това е всичко с регистрацията на потребител и проверката на имейл. Ако имате коментар, въпроси или насърчителни думи, моля, оставете ги в коментара по-долу. И моля, не забравяйте да споделите тази публикация или да препоръчате този сайт на приятелите си, ако го намерите за полезен. Много ме насърчава!

Приятен ден!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Не всички параметри са използвани в SQL израза (Python, MySQL)

  2. Инсталиране на конкретни версии на пакета с pip

  3. Защо резултатите от SQL заявка не се връщат в реда, в който очаквам?

  4. Как да стартирате MySQL или MariaDB Galera Cluster - актуализиран

  5. Правете закъснение / цикъл, за да получите 10 произволни резултата