2010-07-13 244 views
5

當用戶通過他們的電子郵件地址訂閱我的通訊時,使用php,我將如何通過電子郵件向他們發送「激活鏈接」以確認它是他們的電子郵件地址而不是假的。通過電子郵件驗證鏈接

所以此刻我有

PHP:

<?php 
$to = "[email protected]"; 
$subject = "Hi!"; 
$body = "Hi,\n\nHow are you?"; 
if (mail($to, $subject, $body)) { 
    echo "<p>Message successfully sent!</p>"; 
    } else { 
    echo "<p>Message delivery failed...</p>"; 
    } 
?> 

我想我會在$身體改成這樣:

$body = "Please click the link to activate your email \n 
http://www.activationlink.com?"; 

我將如何讓這個如果用戶點擊該鏈接,它會將他們的詳細信息添加到Mysql數據庫,以確認他們是合法用戶?

任何幫助或建議表示讚賞。謝謝

+0

[生成確認碼用於確認電子郵件]的可能重複(http://stackoverflow.com/questions/2088969/generating-confirmation-code-for-an-email-confirmation) – Gordon 2010-07-13 13:14:40

+1

@戈登:不是重複,鏈接問題只會詢問產生隨機數字。這個人詢問了更高級別的整個程序。 – Borealid 2010-07-13 13:18:19

+0

@Borealid yes dup。問題主體和答案的結合包含了所有知識來回答這個問題。 – Gordon 2010-07-13 13:24:04

回答

11

我喜歡做的是:

  • 生成在註冊過程中

  • 商店裏通過E-Mail地址沿着ID的唯一,隨機ID,一個 「確認」 字段(默認:「無」),並在數據庫表中的任何其他數據

  • 發送電子郵件與URL指向激活的唯一ID(如domain.com/activate.php?id=102939505595

  • 激活頁面檢查唯一密鑰是否存在,並將confirmed字段更改爲yes(或1或其他)。

  • 另外還可以選擇保存確認日期/時間,IP地址和用戶代理。

+0

佩卡你是真棒;)最多這是真正的定義。關於這個 – 2015-08-20 06:02:30

6

插入用戶到一個'待決'標誌設置(或'驗證'標誌未設置)的表中。在國旗改變之前,他們不應該做任何事情。如果你想真的徹底,實際上把它們放到users_temp表中。生成一個完全隨機的密鑰並將其與其用戶ID相關聯。您發送給他們的鏈接應該是http://yourwebsite.com/?activate=totallyrandomkeyigeneratedearlier。當您收到激活請求時,使用相應的隨機密鑰打開用戶的有效標誌。

+2

如果您在帳戶被激活時發送電子郵件,請考慮在激活後刪除該ID或檢查是否先前已激活。我有一個系統在調用激活鏈接時總是會觸發一個電子郵件,一個用戶在瀏覽器選項卡中打開該URL幾天。每當他重新啓動瀏覽器並且標籤被恢復時,他會得到一個新的激活確認。 – Gordon 2010-07-13 13:22:18

1

我個人有詳細信息添加到數據庫,並有一個名爲「活動」字段,然後,當他們點擊激活鏈接所有你需要做的就是更新這一塊領域。

你也可以在電子郵件中有一個「這不是我」的鏈接,如果他們點擊這個,你將刪除所有的細節。

+0

有趣的想法不是我 – RSM 2010-07-13 13:27:44

1

生成一個唯一的ID並將其與用戶名/密碼一起存儲在新用戶的某個臨時數據庫條目中。

$tmpID = uniqid(); 

然後,適應在你的電子郵件,身體如鏈接:

$body = "Please click the link to activate your email \n 
http://www.activationlink.com/activateAccount?activate=".$tmpID; 

如果您的服務器上的用戶請求/ activateAccount,檢查對$_GET['activate']參數的數據庫條目,並設置用戶激活(如果匹配)。

爲了確保您的數據庫不只是獲得越來越多的條目,您可以使用一個cron-job來清除比以前更早的條目。 24小時。

+0

這可能是開放的攻擊,因爲uniqid()是可以預見的。確保至少使用more_entropy標誌。 – 2010-07-13 14:57:44

+0

我同意,* more_entropy *標誌使其更安全。 但無論如何,如果您沒有直接訪問服務器,確定確切的時間將會非常困難! (由於uniquid()是基於當前時間的微秒!!)。 因此,如果不能直接訪問,攻擊者必須嘗試很多密鑰才能找到正確的密鑰。因此,對帳戶允許的激活試驗次數的限制可能足以防止發生攻擊,通常應被視爲一種良好做法。 – Javaguru 2010-07-13 15:27:29

1

首先,你需要將2列添加到包含您的數據庫表中的用戶

列應該叫activeactivation_hash

當用戶註冊,你需要插入用戶數據庫,但將active設置爲0,並且activation_hash變成用戶email_address,first_name等的隨機MD5,其中unique_id()在那裏,請確保其位於MD5格式,然後將其存儲在activation_hash列中。

在你的郵件模板添加鏈接,用戶激活,如:

<a href="http://mydomain.registrer.php?process=activate&id=<?php echo $user_id;?>&hash=<?php echo $activation_hash;?>">Activate your account</a>

那麼你的寄存器文件中或你的指點激活鏈接,剛拿到USER_ID &激活通過$_GET進行哈希處理,並根據您的數據庫進行驗證。

如果它們不匹配,則要求用戶輸入他的密碼以發送另一個激活散列。否則將列active設置爲1,以便應用程序的其餘部分知道用戶的狀態。

基本上就是這樣。

+0

你應該通過一個唯一的ID來對隨機值進行散列。如果鏈接包含用戶標識,則不需要它是唯一的,並且MD5哈希保證它不是唯一的。對隨機值進行散列會更好,或者只是使用沒有散列的隨機值。 – 2010-07-13 14:53:36

+0

是針對我的文章或者是它只是額外的信息,如果這樣的話我也解釋說,有應包括數據的陣列的那唯一給該用戶的,以及一些uniqe_id(); – RobertPitt 2010-07-13 15:26:52

+0

指出唯一性和隨機性之間的區別很重要。一個足夠長的隨機密鑰將比唯一密鑰更受歡迎。 – 2010-07-13 17:29:00

5

無需數據庫。你可以發送超鏈接簽署的所有數據哈希

我已經回答了類似的問題,即使過期時間最近。
雖然它是爲密碼恢復鏈接,但思路是一樣的

$token = sha1($time.$email.$salt).dechex(time()).dechex($user_id); 
$link = "http://".$domain."/restorepass/?token=$token"; 

整個令牌會看起來像一個hexdecimal數量,這將是很難猜測它的意思。

在收到只是分裂和解碼回來。
Neat,IMO。

+0

您仍然需要存儲用戶是否被激活。但是,正如所指出的那樣,您不需要存儲散列。 – 2010-07-13 14:35:01

+0

@Marcus您可以在激活時創建用戶帳戶。這就是全部 – 2010-07-13 15:00:20

+0

這是一個整潔的想法,絕對低維護。這意味着哈希完全基於用戶提供的數據,因此需要對某個密鑰進行哈希處理以避免濫用,或者您稱之爲已簽名,因此可能存在一些不對稱算法。 – 2010-07-13 15:18:19

0

這是我的完整的解決方案的情況:

CREATE TABLE signup (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
username VARCHAR(30) NOT NULL, 
password VARCHAR(30) NOT NULL, 
email VARCHAR(30) NOT NULL, 
token VARCHAR(30) NOT NULL, 
verified VARCHAR(50), 
registration_date TIMESTAMP, 
maxdate TIMESTAMP 
); 

Signup MySQL Table

添加註冊頁面signup.php

添加以下形式:

<form name="signupform" method="post" action="process.php"> 
    Username: 
    <input type="text" name="username"> 
    <br> Password: 
    <input type="text" name="password"> 
    <br> Email: 
    <input type="text" name="email"> 
    <br> 
    <input type="submit" value="Signup"> 
</form> 

創建process.php頁:

<?php 
$username = $_POST['username']; 
$email = $_POST['email']; 
$password = $_POST['password']; 
date_default_timezone_set('America/New_York'); 
$registration_date = date('Y-m-d H:i:s'); 
$verified = 0; 
$maxdate = date('Y-m-d H:i:s', strtotime($registration_date . ' +1 day')); 
$salt = uniqid(mt_rand() , true); 
$token = msha1(registration_date . md5($salt)); 
$sql = "INSERT INTO signup (username, password, email, token, verified, registration_date, maxdate) VALUES ('$username', '$password', '$email', '$token', '$verified', '$registration_date', '$maxdate')"; 

if (mysqli_query($conn, $sql)) 
    { 
    $msg = 'Please click this link to verify your email: http://www.yourdomain.com/verifyemail.php?token=' . $token; 
    mail($email, $subject, $msg); 
    } 
    else 
    { 
    echo mysql_error(); 
    } 

?> 

之後創建verifyemail。PHP

<?php 
$token = $_REQUEST['token']; 
date_default_timezone_set('America/New_York'); 
$current_time = date('Y-m-d H:i:s'); 
$sql = "SELECT * FROM users WHERE token='$token' AND maxtime >'$current_time' AND verified=0"; 
$result = mysqli_query($conn, $sql); 
$notverified = mysqli_num_rows($result); 

if ($notverified) 
    { 
    $sql = "update signup set verified=1 where token='$token'"; 
    $result = mysqli_query($conn, $sql); 
    if ($result) 
     { 
     echo 'Email verified'; 
     } 
     else 
     { 
     echo 'Error'; 
     } 
    } 
    else 
    { 
    echo 'Link expired'; 
    } 

?>