如何用PHP搭建会员注册及登陆系统(2)

请注意,本文编写于 1696 天前,最后修改于 230 天前,其中某些信息可能已经过时。

Activate.Php

这个页面自动检查网址中所传入的用户的id和激活码(用户点击右键中的链接后),如果信息与数据库中存储的内容一致,将自动更新数据库中激活码一栏为Yes。

    <?php
    require('includes/config.php');
    
    //collect values from the url
    $memberID = trim($_GET['x']);
    $active = trim($_GET['y']);
    
    //if id is number and the active token is not empty carry on
    if(is_numeric($memberID) && !empty($active)){
    
        //update users record set the active column to Yes where the memberID and active value match the ones provided in the array
        $stmt = $db->prepare("UPDATE members SET active = 'Yes' WHERE memberID = :memberID AND active = :active");
        $stmt->execute(array(
            ':memberID' => $memberID,
            ':active' => $active
        ));
    
        //if the row was updated redirect the user
        if($stmt->rowCount() == 1){
    
            //redirect to login page
            header('Location: login.php?action=active');
            exit;
    
        } else {
            echo "Your account could not be activated.";
        }
    
    }
    ?>

Login.Php

现在让我们来新建一个登陆页面,让用户填写账号和密码。

    <form role="form" method="post" action="" autocomplete="off">
    
        <div class="form-group">
            <input type="text" name="username" id="username" class="form-control input-lg" placeholder="User Name" value="<?php if(isset($error)){ echo $_POST['username']; } ?>" tabindex="1">
        </div>
    
        <div class="form-group">
            <input type="password" name="password" id="password" class="form-control input-lg" placeholder="Password" tabindex="3">
        </div>
    
        <div class="row">
            <div class="col-xs-9 col-sm-9 col-md-9">
                 <a href='reset.php'>Forgot your Password?</a>
            </div>
        </div>
    
        <hr>
        <div class="row">
            <div class="col-xs-6 col-md-6"><input type="submit" name="submit" value="Login" class="btn btn-primary btn-block btn-lg" tabindex="5"></div>
        </div>
    </form>

通过接受$_GET['action'],这个页面同时将用作显示“激活成功”、“密码修改”等信息。

    if(isset($_GET['action'])){
    
        //check the action
        switch ($_GET['action']) {
            case 'active':
                echo "<h2 class='bg-success'>Your account is now active you may now log in.</h2>";
                break;
            case 'reset':
                echo "<h2 class='bg-success'>Please check your inbox for a reset link.</h2>";
                break;
            case 'resetAccount':
                echo "<h2 class='bg-success'>Password changed, you may now login.</h2>";
                break;
        }
    
    }

用户填写账户密码,本页面加密明文密码后,与数据库中存储的信息比对,如果信息一致,则设置 $_SESSION\['loggedin'\]ture

    public function login($username,$password){
    
        $hashed = $this->get_user_hash($username);
    
        if($this->password_verify($password,$hashed) == 1){
    
            $_SESSION['loggedin'] = true;
            return true;
        }
    }
    
    //process login form if submitted
    if(isset($_POST['submit'])){
    
        $username = $_POST['username'];
        $password = $_POST['password'];
    
        if($user->login($username,$password)){ 
    
            header('Location: memberpage.php');
            exit;
    
        } else {
            $error[] = 'Wrong username or password or your account has not been activated.';
        }
    
    }//end if submit

Logout.Php

登出用户很简单,代码如下:

    //logout
    $user->logout();

用户登出后,自动跳转。

Memberpage.Php

用户登陆后,自动跳转至会员页面(非必须),为了确保用户是登陆状态,我们需要做一个验证:

    //if not logged in redirect to login page
    if(!$user->is_logged_in()){ header('Location: login.php'); }

本页面暂时不需要过多的内容。

    <h2>Member only page</h2>
    <p><a href='logout.php'>Logout</a></p>

Reset.Php

所有系统都需要一个密码重置功能,这里我们通过查找用户提供的邮箱地址,来确认用户id,然后生成激活码(token),发送激活邮件,用户点击后,即可输入新密码,并自动更新数据库中的信息。

    <form role="form" method="post" action="" autocomplete="off">
        <div class="form-group">
            <input type="email" name="email" id="email" class="form-control input-lg" placeholder="Email" value="" tabindex="1">
        </div>
    
        <hr>
        <div class="row">
            <div class="col-xs-6 col-md-6"><input type="submit" name="submit" value="Sent Reset Link" class="btn btn-primary btn-block btn-lg" tabindex="2"></div>
        </div>
    </form>

如果 $_GET['action'] 非空,则显示集合中的信息。

    <?php
    if(isset($_GET['action'])){
    
        //check the action
        switch ($_GET['action']) {
            case 'active':
                echo "<h2 class='bg-success'>Your account is now active you may now log in.</h2>";
                break;
            case 'reset':
                echo "<h2 class='bg-success'>Please check your inbox for a reset link.</h2>";
                break;
        }
    }
    ?>

然后执行表单,确保邮件地址属于已注册的用户。

    //email validation
    if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)){
        $error[] = 'Please enter a valid email address';
    } else {
        $stmt = $db->prepare('SELECT email FROM members WHERE email = :email');
        $stmt->execute(array(':email' => $_POST['email']));
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
    
        if(empty($row['email'])){
            $error[] = 'Email provided is not on recognised.';
        }
    }

生成激活码(token)。

    //create the activation code
    $token = md5(uniqid(rand(),true));

然后更新用户信息,生成激活码,发送邮件,包含resetPassword.php?key=$token链接。

    $stmt = $db->prepare("UPDATE members SET resetToken = :token, resetComplete='No' WHERE email = :email");
    $stmt->execute(array(
        ':email' => $row['email'],
        ':token' => $token
    ));
    
    //send email
    $to = $row['email'];
    $subject = "Password Reset";
    $body = "Someone requested that the password be reset. nnIf this was a mistake, just ignore this email and nothing will happen.nnTo reset your password, visit the following address: ".DIR."resetPassword.php?key=$token";
    $additionalheaders = "From: <".SITEEMAIL.">rn";
    $additionalheaders .= "Reply-To: $".SITEEMAIL."";
    mail($to, $subject, $body, $additionalheaders);
    
    //redirect to index page
    header('Location: login.php?action=reset');
    exit;

ResetPassword.Php

首先检查用户的激活码

    $stmt = $db->prepare('SELECT resetToken, resetComplete FROM members WHERE resetToken = :token');
    $stmt->execute(array(':token' => $_GET['key']));
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    
    //if no token from db then kill the page
    if(empty($row['resetToken'])){
        $stop = 'Invalid token provided, please use the link provided in the reset email.';
    } elseif($row['resetComplete'] == 'Yes') {
        $stop = 'Your password has already been changed!';
    }

如果$stop已设置,则显示信息

    if(isset($stop)){
        echo "<p class='bg-danger'>$stop</p>";
    }

如果没有错误信息,则显示修改密码表单

    <form role="form" method="post" action="" autocomplete="off">
        <div class="row">
            <div class="col-xs-6 col-sm-6 col-md-6">
                <div class="form-group">
                    <input type="password" name="password" id="password" class="form-control input-lg" placeholder="Password" tabindex="1">
                </div>
            </div>
            <div class="col-xs-6 col-sm-6 col-md-6">
                <div class="form-group">
                    <input type="password" name="passwordConfirm" id="passwordConfirm" class="form-control input-lg" placeholder="Confirm Password" tabindex="1">
                </div>
            </div>
        </div>
    
        <hr>
        <div class="row">
            <div class="col-xs-6 col-md-6"><input type="submit" name="submit" value="Change Password" class="btn btn-primary btn-block btn-lg" tabindex="3"></div>
        </div>
    </form>

表单提交后,验证密码,加密后存储至数据库中。设置resetComplete值为Yes,以示密码修改成功。

    //if form has been submitted process it
    if(isset($_POST['submit'])){
    
        //basic validation
        if(strlen($_POST['password']) < 3){
            $error[] = 'Password is too short.';
        }
    
        if(strlen($_POST['passwordConfirm']) < 3){
            $error[] = 'Confirm password is too short.';
        }
    
        if($_POST['password'] != $_POST['passwordConfirm']){
            $error[] = 'Passwords do not match.';
        }
    
        //if no errors have been created carry on
        if(!isset($error)){
    
            //hash the password
            $hashedpassword = $user->password_hash($_POST['password'], PASSWORD_BCRYPT);
    
            try {
    
                $stmt = $db->prepare("UPDATE members SET password = :hashedpassword, resetComplete = 'Yes'  WHERE resetToken = :token");
                $stmt->execute(array(
                    ':hashedpassword' => $hashedpassword,
                    ':token' => $row['resetToken']
                ));
    
                //redirect to index page
                header('Location: login.php?action=resetAccount');
                exit;
    
            //else catch the exception and show the error.
            } catch(PDOException $e) {
                $error[] = $e->getMessage();
            }
        }
    }

总结

到此为止,就为大家展示了会员登陆系统的基础框架,大家可以在此基础上制作控制面板等附加功能。 完整代码可以在原作者的github中下载:https://github.com/daveismynamecom/loginregister

添加新评论

评论列表