如何将验证链接发送到电子邮件地址?

时间:2013-01-12 04:09:53

标签: php mysql

我有一个php登录系统,但缺乏功能。我想在用户登录前向用户发送电子邮件地址,他们必须点击链接激活帐户。我也想让他们需要新的密码,以防他们忘记了他们的密码......除了这两个问题,其他一切正常。我是否实现了这一目标?感谢

我在数据库中的表users中拥有的内容:

1   id          int(11)       AUTO_INCREMENT    
2   username    varchar(255)        
3   password    char(64)    
4   salt        char(16)    
5   email       varchar(255)

register.php     

// First we execute our common code to connection to the database and start the session 
require("common.php"); 

// This if statement checks to determine whether the registration form has been submitted 
// If it has, then the registration code is run, otherwise the form is displayed 
if(!empty($_POST)) 
{ 
    // Ensure that the user has entered a non-empty username 
    if(empty($_POST['username'])) 
    { 
        echo "Please enter a username."; 
    } 

    // Ensure that the user has entered a non-empty password 
    if(empty($_POST['password'])) 
    { 
        die("Please enter a password."); 
    } 

    // Make sure the user entered a valid E-Mail address 
    // filter_var is a useful PHP function for validating form input, see:
    if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) 
    { 
        die("Invalid E-Mail Address"); 
    } 

    $query = " 
        SELECT 
            1 
        FROM users 
        WHERE 
            username = :username 
    "; 

    $query_params = array( 
        ':username' => $_POST['username'] 
    ); 

    try 
    { 
        // These two statements run the query against your database table. 
        $stmt = $db->prepare($query); 
        $result = $stmt->execute($query_params); 
    } 
    catch(PDOException $ex) 
    { 
        // Note: On a production website, you should not output $ex->getMessage(). 
        // It may provide an attacker with helpful information about your code.  
        die("Failed to run query: " . $ex->getMessage()); 
    } 

    $row = $stmt->fetch(); 


    if($row) 
    { 
        die("This username is already in use"); 
    } 

    // Now we perform the same type of check for the email address, in order 
    // to ensure that it is unique. 
    $query = " 
        SELECT 
            1 
        FROM users 
        WHERE 
            email = :email 
    "; 

    $query_params = array( 
        ':email' => $_POST['email'] 
    ); 

    try 
    { 
        $stmt = $db->prepare($query); 
        $result = $stmt->execute($query_params); 
    } 
    catch(PDOException $ex) 
    { 
        die("Failed to run query: " . $ex->getMessage()); 
    } 

    $row = $stmt->fetch(); 

    if($row) 
    { 
        die("This email address is already registered"); 
    } 

    // An INSERT query is used to add new rows to a database table. 
    // Again, we are using special tokens (technically called parameters) to 
    // protect against SQL injection attacks. 
    $query = " 
        INSERT INTO users ( 
            username, 
            password, 
            salt, 
            email 
        ) VALUES ( 
            :username, 
            :password, 
            :salt, 
            :email 
        ) 
    "; 

    $salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647)); 


    $password = hash('sha256', $_POST['password'] . $salt); 

    for($round = 0; $round < 65536; $round++) 
    { 
        $password = hash('sha256', $password . $salt); 
    } 


    $query_params = array( 
        ':username' => $_POST['username'], 
        ':password' => $password, 
        ':salt' => $salt, 
        ':email' => $_POST['email'] 
    ); 

    try 
    { 
        // Execute the query to create the user 
        $stmt = $db->prepare($query); 
        $result = $stmt->execute($query_params); 
    } 
    catch(PDOException $ex) 
    { 

    } 
    header("Location: login.php"); 
    die("Redirecting to login.php"); 
} 

?> 
<h1>Register</h1> 
<form action="" method="post"> 
Username:<br /> 
<input type="text" name="username"  required value="" /> 
<br /><br /> 
E-Mail:<br /> 
<input type="text" name="email" required value="" /> 
<br /><br /> 
Password:<br /> 
<input type="password" required  name="password" value="" /> 
<br /><br /> 
<input type="submit"  value="Register" /> 
</form>

的login.php

<?php 

// First we execute our common code to connection to the database and start the session 
require("common.php"); 

$submitted_username = '';
if(!empty($_POST)) 
{ 
    $query = " 
        SELECT 
            id, 
            username, 
            password, 
            salt, 
            email 
        FROM users 
        WHERE 
            username = :username 
    "; 

    // The parameter values 
    $query_params = array( 
        ':username' => $_POST['username'] 
    ); 

    try 
    { 
        // Execute the query against the database 
        $stmt = $db->prepare($query); 
        $result = $stmt->execute($query_params); 
    } 
    catch(PDOException $ex) 
    { 
        die("Failed to run query: " . $ex->getMessage()); 
    } 

    $login_ok = false; 

    $row = $stmt->fetch(); 
    if($row) 
    { 

        $check_password = hash('sha256', $_POST['password'] . $row['salt']); 
        for($round = 0; $round < 65536; $round++) 
        { 
            $check_password = hash('sha256', $check_password . $row['salt']); 
        } 

        if($check_password === $row['password']) 
        { 
            $login_ok = true; 
        } 
    } 

    if($login_ok) 
    { 

        unset($row['salt']); 
        unset($row['password']); 

        $_SESSION['user'] = $row; 

        // Redirect the user to the private members-only page. 
        header("Location: private.php"); 
        die("Redirecting to: private.php"); 
    } 
    else 
    { 
        // Tell the user they failed 
        print("The Username/Password is invalid."); 

        $submitted_username = htmlentities($_POST['username'], ENT_QUOTES, 'UTF-8'); 
    } 
} 

?> 
<h1>Login</h1> 
<form action="login.php" method="post"> 
Username:<br /> 
<input type="text" name="username" required value="<?php echo $submitted_username; ?>" /> 
<br /><br /> 
Password:<br /> 
<input type="password" name="password" value="" required /> 
<br /><br /> 
<input type="submit" value="Login" /> 
</form> 
<a href="register.php">Register</a>

2 个答案:

答案 0 :(得分:3)

一般来说,要验证电子邮件,您需要做的是在注册时创建一个随机字符串;并使用新注册的用户ID或电子邮件地址将该字符串存储在数据库中。然后在您的电子邮件中,您发送一个附加了该字符串的链接。 EX:

<a href="http://www.mywebsite.com/activate.php?v=329857320952">Activate your account now</a>

然后,当他们转到该链接时,您使用$ _GET ['v']从链接获取该值并检查您的数据库...然后您在数据库中搜索该特定值并编辑/删除该行用户与该值相关联。

然后,在此过程中,您将有两种方法可以让用户注册。您可以将列周长值设置为“已注册”或“1”或几乎任何内容;或者您可以删除具有该存储的注册值的行...

这意味着每次用户登录时,您需要检查该新列值,或者该用户是否存在于'not_activated_yet'表中。有很多方法可以做到这一点,但这是一个非常基本的程序。

以下是一些可以帮助您的基本脚本...... 在用户满足您将数据放入数据库的php附近的所有注册要求后,您可以使用它向他们发送电子邮件...

<?php
$to = "$user_email";
 $subject = "Your Account Information!";
  $body = <<<EMAIL
Hello {$user_firstname} {$user_lastname}, here is your account information!

Username:{$user_username}
Password:{$user_pass}

Please activate your account by clicking the following activation link:
http://www.mywebsite.com/activate.php?aid={$aid}

EMAIL;

$headers = 'From: notify@yourwebsite.com' . "\r\n" .
    'Reply-To: notify@yourwebsite.com' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

if (mail($to, $subject, $body, $headers)) {
   echo("<p>Your account information was successfully sent to your email - ($user_email)!<br><br>Please open your email and click the activation link to activate your account.</p><br><p>If you do not see your account information in your inbox within 60 seconds please check your spam/junk folder.</p>");
  } else {
   echo("<p> Unfortunately, your account information was <u>unsuccessfully</u> sent to your email - ($user_email).</p>");
  }
?>

至于更改密码,有两种不同的情况。一个是他们知道他们的旧密码,只是想改变它...这就像有一个表单,他们输入他们的电子邮件,oldpassword和newpassword ...你检查在你的数据库中输入的密码和电子邮件是否使用相同的行...如果这是真的,您只需运行UPDATE查询以使用新的更新其密码字段...

对于密码重置最简单的方法可能是在登录页面上某处说忘了密码?使用链接将其重定向到他们输入电子邮件的页面;就像注册一样,你给他们发了一封电子邮件。然后存储唯一密钥和用户ID ...一旦在该链接上,他们输入一个新密码;您可以在其中找到存储用户id和临时密钥的表;然后更新该用户ID的表密码。

编辑:此外,如果您想要而不是所有设置临时密钥,您只需将电子邮件发送到密码,但假设您的数据库中的密码已加密,您将不得不使用临时密钥。

忘记密码相关代码(第1部分发送):

<?php
if(isset($_POST['submit'])){
$email = $_POST['email'];
//generate a random string
/// insert the key and email into a row in some table of your choosing.
///send email to the email address with the code above.
///echo success so the user knows everything worked.
}
?>
<form action='' method='POST>
<input type='text' name='pass'>
<input type='submit' name='submit' value='Send Password Request'>
</form>

第2部分处理:

<?php
$key = $_GET['key']; //gets key from the link you sent in your e-mail; what temporarily connects to that user.
// search your database table for that key
// once you have that users id delete the row in the password-request table and insert the password into your users table row.
?>

答案 1 :(得分:0)

只需在users表中添加2个字段,表示令牌和状态。现在创建一个链接,在最后添加此令牌(http://yourdomain.com/users/accountactivation/34gg456sas78ud)并通过电子邮件发送。当用户点击此链接时,控件将转到帐户激活,其中运行查询以验证数据库中是否存在此令牌。如果是,请将该用户的状态更改为1,并同时更改/删除表中的令牌,以使链接过期。当用户登录时,检查用户状态是否为1.如果是,用户可以登录,否则会显示一条消息以检查电子邮件以激活帐户。