How to implement email verification with php? - php

I'm using php and laravel as a framework. I want to let user be able to activate their accounts through email.
I have no experience with this however. I already set up a form that asks for username, email and password.
Would this still be the best way to go about it in 2013?
http://net.tutsplus.com/tutorials/php/how-to-implement-email-verification-for-new-members/?search_index=8
So:
I need to create a database field for a hashed password.
On user account creation create a random password for this field and email it to them.
Provide link with the password and user id in the url to a page that compares the emailed password with password in db field.
Activate account(set active to 1) when the passwords match.
Something along those lines?

Email verification is a simple process there is two way to verify email either by sending code to user email address or by sending link both works same here is a sample code from a tutorial http://talkerscode.com/webtricks/account-verification-system-through-email-using-php.php on TalkersCode
// Table Scheme for Verify Table
CREATE TABLE `verify` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` text NOT NULL,
`password` text NOT NULL,
`code` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
// Table Scheme for verified_user table
CREATE TABLE `verified_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` text NOT NULL,
`password` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
if(isset($_POST['register']))
{
$email_id=$_POST['email'];
$pass=$_POST['password'];
$code=substr(md5(mt_rand()),0,15);
mysql_connect('localhost','root','');
mysql_select_db('sample');
$insert=mysql_query("insert into verify values('','$email','$pass','$code')");
$db_id=mysql_insert_id();
$message = "Your Activation Code is ".$code."";
$to=$email;
$subject="Activation Code For Talkerscode.com";
$from = 'your email';
$body='Your Activation Code is '.$code.' Please Click On This link Verify.php?id='.$db_id.'&code='.$code.'to activate your account.';
$headers = "From:".$from;
mail($to,$subject,$body,$headers);
echo "An Activation Code Is Sent To You Check You Emails";
}
if(isset($_GET['id']) && isset($_GET['code']))
{
$id=$_GET['id'];
$code=$_GET['id'];
mysql_connect('localhost','root','');
mysql_select_db('sample');
$select=mysql_query("select email,password from verify where id='$id' and code='$code'");
if(mysql_num_rows($select)==1)
{
while($row=mysql_fetch_array($select))
{
$email=$row['email'];
$password=$row['password'];
}
$insert_user=mysql_query("insert into verified_user values('','$email','$password')");
$delete=mysql_query("delete from verify where id='$id' and code='$code'");
}
}

In your explanation you forgot the most important part: the random hash. Compare the hash, not the password. The guide explains it correctly.
The guide looks solid.
I would implement a better random password generator though, rand(1000,5000) is really not very good. You could even set up a first-time logon that asks for a password.

A warning: According to the PHP Manual, EREGI is DEPRECATED! http://php.net/manual/en/function.eregi.php
preg_match would be a good option. http://www.php.net/manual/en/function.preg-match.php

Related

How to reset password that is generated with md5() and crypt()

I was working on my project and I forget Admin users password. Here is users table:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(50) NOT NULL,
`password` varchar(32) NOT NULL,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
INSERT INTO `users` (`id`, `email`, `password`, `name`) VALUES
(7, 'ikhlassons#gmail.com', '078bbb4bf0f7117fb131ec45f15b5b87', 'Ikhlas Sons'),
(10, 'wali_essa#hotmail.com', '078bbb4bf0f7117fb131ec45f15b5b87', 'essa');
Can anyone tell me how reset password in php that is generated with md5() and cryp()
Here's how the password is generated:
$hash = crypt($entered_password,"");
$hash = md5($hash);
You need an extra column named, for example, password_reset_token. When a user wants to recover his password, your app must generate a (long enough) random string and store it in than password_reset_token field.
Then you create a script that receives that token by $_GET (i.e.: example.com/password-reset/?token=982dh89h2w9h92hd), check if it exists in the Users table and, if correct, promtps a form to reset the password for that user.
You have to email that link (example.com/password-reset/?token=982dh89h2w9h92hd) to the user, telling him to click on it to reset his password.
This should work:
$hash = crypt("passpass","");
$hash = md5("passpass");
echo $hash;
Or this:
$hash = crypt("passpass","");
echo $hash;
Remember your password is passpass. Copy the code into users.password field in mysql database. And use passpass as password when login.

Php pdo inserting firm with session data

I am working on an application that has different forms that a logged in user can fill out and submit. For example, an artist is able to submit their video through a form and that movie will be saved and uploaded to the database.
However, I would like when a form is submitted for it to automatically connect the userID and userEmail to the form when it is submitted so that I can easily check for either user id or email when pulling back data.
I have tried several different methods of doing this and nothing has worked so any help is much appreciated. I am also using foreign keys in my database tables but I do not understand how that works in connecting to a table.
So here is my table setup for users and for movies
Users table
CREATE TABLE IF NOT EXISTS. `users` (
`userID` int(11) NOT NULL. AUTO_INCREMENT,
`userEmail` varchar(100) NOT NULL,
`userPass` varchar(100) NOT NULL,
`userType` varchar(6) NOT NULL,
`agreement` enum('Yes', 'No') NOT NULL,
`userStatus` enum('Y','N') NOT NULL. DEFAULT 'N',
`tokenCode` varchar(100) NOT NULL,
PRIMARY KEY (`userID`),
UNIQUE KEY `userEmail` (`userEmail`)
) ENGINE= MyISAM DEFAULT. CHARSET=latin1. AUTO_INCREMENT=1 ;
Movies Table
CREATE TABLE `movies` (
`userID` int(11) NOT NULL,
`userEmail` varchar(250) NOT. NULL,
`movie_name` varchar(300) NOT NULL,
FOREIGN KEY (userID) Refrences users(userID),
FOREIGN KEY (userEmail) REFRENCES users(userEmail),
UNIQUE KEY `movie_name` (`movie_name`)
) ENGINE=MyISAM DEFAULT. CHARSET=latin1;
The Form page is here
( I tried adding the SESSION data to the POST here and tried the GET method to add SESSION data neither of which worked)
if(isset($_POST['submit']))
{
$email = trim($_POST['email']);
$movie = trim($_POST['movie']);
if($user_home->upload($email, $movie))
{
header("Location: Artist_Uploads.php?inserted");
}
else
{
header("Location: Artist_Uploads.php?failure");
}
}
<form action="Artist_Uploads.php" method="post" name="upload">
<input name="email" type="hidden" value="<?php echo. htmlentities($row['userEmail']); ?>" />
<input name="movie" type="text" />
<input name="submit" type="submit" />
</form>
Page that processes form submission
public function upload($email,$movie) { try
{
$stmt = $this->conn->prepare("INSERT INTO movies(userEmail, movie_name) VALUES(:email, :movie)");
$stmt->bindValue(":email",$email);
$stmt->bindparam(":movie",$movie);
$stmt->execute();
return true;
}
catch(PDOException $e)
{
echo $e->getMessage();
return false;
}
}
I have tried insert lasted() below the return true and before the return true.
Tried adding VALUES ('','$_SESSION[cuserID]','$_SESSION[userEmail]','') :movies");.
I also tried adding the _SESSION data in the bindValue or the bindCol neither of those worked either.
I also tried adding INSERT INTO movies FROM users.userID, users.userEmail but that did not work either.
So I do not know how to get it to insert the userID and userEmail without outputting it into the form then inserting it that way but that seems to dangerous and open to injection because someone could easily manipulate that info or
get the users ID and start playing with it. So any suggestions or pointers would be much appreciated. Thank you in advance.
The user ID or username whatever you use to uniquely and permanently identify each user should be stored in the session right after the user is authenticated. I say permanently because by using the email and then even setting up foreign key constraints on the email you are looking for a world of pain. Don't do that. Use something that would never be modified by the user. Typically users aren't allowed to modify their username and it would be pointless to give a user the option to modify their user id.
First you authenticate (something like this):
<?php
if ($user->authenticate($_POST['username'], $_POST['password'])) {
session_start();
$_SESSION['userid'] = $user->getUserId();
}
else {
echo "invalid password";
}
On subsequent requests, make sure you do session_start() first, and then you can just retrieve the information from the database using the value stored in the session. No need to send it in the form. In fact, sending it in the form would be a huge security risk because people could upload videos to other users' accounts.
session_start();
// Make sure user is logged in
if (!isset($_SESSION['userid'])) {
header("Location: login.php");
}
// Pull their info from the database
$stmt = $this->conn->prepare("SELECT * FROM users WHERE userid = ?");
$stmt->bindValue(1, $_SESSION['userid']);
$stmt->execute();
$user = $stmt->fetch();
Then you can execute your other queries based on the values you get in $user. Similar to what I mentioned earlier, get rid of emails from tables where it is irrelevant. You are duplicating information across tables and modifying the value would be very difficult. You also want to add some sort of unique way to identify the movies as well:
CREATE TABLE `movies` (
`movieID` int(11) NOT NULL. AUTO_INCREMENT,
`userID` int(11) NOT NULL,
`movie_name` varchar(300) NOT NULL,
FOREIGN KEY (userID) Refrences users(userID),
UNIQUE KEY `movie_name` (`movie_name`)
) ENGINE=MyISAM DEFAULT. CHARSET=latin1;
Then query:
public function upload($userid,$movie) {
try
{
$stmt = $this->conn->prepare("INSERT INTO movies(userID, movie_name)
VALUES(:userid, :movie)");
$stmt->bindValue(":userid",$userid);
$stmt->bindparam(":movie",$movie);
$stmt->execute();
return true;
}
catch(PDOException $e) {
echo $e->getMessage();
return false;
}
}
There are several issues going on here. I can't say I completely understand the errors you're seeing (please post any error messages as part of the question).
However, I do see a potentially significant issue with your table schema. If the movies table has users.userID as a foreign key, it should not need a userEmail attribute at all (nor its associated foreign key), as this information is obtained by joining users and movies on userID. In addition, trying to build a foreign key on userEmail is extra problematic, as users.userEmail is not guaranteed to be unique.
Answer:
On the page that process the form do the following
If (isset ($_POST ['submit']))
{
$email = $_SESSION ['userEmail'];
Everything else is normal and it works perfectly. Just make sure you have sessions setup or it will not work.

Some form data submitted by new users is a duplicate of a value submitted by a previous user

There's a simple registration form on this page which is used to collect details of new registrations. The registration script is quite poorly coded however does very little to manipulate the data:
$first_name = stripslashes($_POST['first_name']);
$last_name = stripslashes($_POST['last_name']);
$foo = stripslashes($_POST['foo']);
...
$first_name = mysql_real_escape_string($first_name);
$last_name = mysql_real_escape_string($last_name);
$foo = mysql_real_escape_string($foo);
...
if(mysql_query(INSERT INTO blessedbirthretreat2015 (first_name, last_name, foo...)
VALUES ('$first_name','$last_name','$foo'...))) {
}
Then an email is sent with a few of the user's details. However, several registrations have been saved using the values from a previous registration, these are received as such in both the email and the table. The table looks like this:
Link to table image
As can be seen, entries 12-26 use the same data for the following fields:
mobile_phone varchar(16)
email varchar(32)
address_1 varchar(512)
post_code varchar(16)
emergency_name varchar(64)
emergency_phone varchar(16)
medical_conditions varchar(512)
The following are not duplicated.
id int(4)
first_name varchar(16)
last_name varchar(16)
gender varchar(8)
date_of_birth varchar(16)
The other curiosity I've noticed is that the registration emails were received within 1-2 minutes of each other for all of these users - it is incredibly unlikely that they registered one after another. Any ideas how this might be occurring?

PHP/MYSQL: table was not created in wamp server

when I run this php file in my wamp server it connects to database, selects database but not create table .
the output is this:
connected to database succussfully.
connected to database store_db succussfully.
table users was not created.
what is the problem???
php code:
<?php
$sql='CREATE TABLE users
(
PID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(PID),
NAME CHAR(20),
PASSWORD CHAR(15),
)';
mysql_connect("localhost","root","") or die('could not connect to database.');
echo 'connected to database succussfully.<br>';
mysql_select_db('store_db') or die('database store_db not found.');
echo 'connected to database store_db succussfully.<br>';
mysql_query($sql) or die('table users was not created');
echo 'table users was created in database store_db succussfully.<br>';
?>
<?php
$sql='CREATE TABLE users
(
PID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(PID),
NAME CHAR(20),
PASSWORD CHAR(15),
)';
remove the comma after PASSWORD CHAR(15),
in the event of an error, you can always retrieve errors using mysql_error().
however. you should not be using the old mysql functions. much better and more secure options exist in the PDO and MySQLi extensions.
Your $sql:
$sql='CREATE TABLE users
(
PID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(PID),
NAME CHAR(20),
PASSWORD CHAR(15),
)';
should be:
$sql='CREATE TABLE users
(
PID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(PID),
NAME CHAR(20),
PASSWORD CHAR(15)
)';
You should remove comma right after PASSWORD CHAR(15)
To get the proper error message always use below code so that you can figure out exact error in future.
mysql_query($sql) or die(mysql_error());
Make sure the MySQL user you are attempting to create the table with has permissions to do so. (e.g. the user has been granted the 'CREATE' privileges for that database.)

OOP PHP user class (usercake) not adding to database

I recently found this little user class script called usercake (http://usercake.com/), has all the basic functionality and seems to work very well.
My problem: The first user gets added to the database fine, but after that it is not working. Clearly there's just something slightly wrong that I'm not figuring out ( i do not know oop php very well). No errors occure (that i can see), and the email gets sent out.
I've installed it multiple places with the same fate. I'd like to fix it because using this script saves a lot of reinventing the wheel time.
Here is the URL where I have it: http://rawcomposition.com/birding/loggedin/register.php
Here is the function that gets called once everything is validated:
public function userCakeAddUser()
{
global $db,$emailActivation,$websiteUrl,$db_table_prefix;
//Prevent this function being called if there were construction errors
if($this->status)
{
//Construct a secure hash for the plain text password
$secure_pass = generateHash($this->clean_password);
//Construct a unique activation token
$this->activation_token = generateActivationToken();
//Do we need to send out an activation email?
if($emailActivation)
{
//User must activate their account first
$this->user_active = 0;
$mail = new userCakeMail();
//Build the activation message
$activation_message = lang("ACTIVATION_MESSAGE",array($websiteUrl,$this->activation_token));
//Define more if you want to build larger structures
$hooks = array(
"searchStrs" => array("#ACTIVATION-MESSAGE","#ACTIVATION-KEY","#USERNAME#"),
"subjectStrs" => array($activation_message,$this->activation_token,$this->unclean_username)
);
/* Build the template - Optional, you can just use the sendMail function
Instead to pass a message. */
if(!$mail->newTemplateMsg("new-registration.txt",$hooks))
{
$this->mail_failure = true;
}
else
{
//Send the mail. Specify users email here and subject.
//SendMail can have a third parementer for message if you do not wish to build a template.
if(!$mail->sendMail($this->clean_email,"New User"))
{
$this->mail_failure = true;
}
}
}
else
{
//Instant account activation
$this->user_active = 1;
}
if(!$this->mail_failure)
{
//Insert the user into the database providing no errors have been found.
$sql = "INSERT INTO `".$db_table_prefix."Users` (
`Username`,
`Username_Clean`,
`Password`,
`Email`,
`ActivationToken`,
`LastActivationRequest`,
`LostPasswordRequest`,
`Active`,
`Group_ID`,
`SignUpDate`,
`LastSignIn`
)
VALUES (
'".$db->sql_escape($this->unclean_username)."',
'".$db->sql_escape($this->clean_username)."',
'".$secure_pass."',
'".$db->sql_escape($this->clean_email)."',
'".$this->activation_token."',
'".time()."',
'0',
'".$this->user_active."',
'1',
'".time()."',
'0'
)";
return $db->sql_query($sql);
}
}
}
And here is the table structure:
CREATE TABLE IF NOT EXISTS `userCake_Users` (
`User_ID` int(11) NOT NULL AUTO_INCREMENT,
`Username` varchar(150) NOT NULL,
`Name` varchar(100) NOT NULL,
`Username_Clean` varchar(150) NOT NULL,
`Password` varchar(225) NOT NULL,
`Email` varchar(150) NOT NULL,
`ActivationToken` varchar(225) NOT NULL,
`LastActivationRequest` int(11) NOT NULL,
`LostPasswordRequest` int(1) NOT NULL DEFAULT '0',
`Active` int(1) NOT NULL,
`Group_ID` int(11) NOT NULL,
`SignUpDate` int(11) NOT NULL,
`LastSignIn` int(11) NOT NULL,
PRIMARY KEY (`User_ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
To me, there are 2 possibilities why it is not adding further users after the first one is added:
First, $this->mail_failure flag is set to TRUE for the following user accounts after the first user is created. But this scenario is not likely because it is the same code that has run successfully for the first user and therefore there is no reason why the flag should be TRUE for others.
Second possibility is that $this->status is FALSE for the second user account. If false, the method userCakeAddUser() does not do anything. The reasons why this flag could be false is either the username or the email address already exists.
Are you using the same username or email address you used for the first account for the second account as well? I'm sure you must not be using the same username but perhaps the same email address. The usercake classes does not allow the same username or same email addresses.
Hope this helps.
I would do 4 things with this uggly code :
1) to enable the error_reporting mode so that you can see something in case sthg occurs :
error_reporting(E_ALL);
2) to test this INSERT sql straight into the dB to make sure it's working properly, and validate this piece of code. If the sql INSERT request is valid, then check the access conditions to these SQL request, like Abhay said above,
3) As we do not have your all config available, a guess game is difficult. So I'd suggest you to add one NULL field for the AI User_ID.
$sql = "INSERT INTO `".$db_table_prefix."Users` (
`User_ID`, // Add this here
`Username`,
`Username_Clean`,
`Password`,
`Email`,
`ActivationToken`,
`LastActivationRequest`,
`LostPasswordRequest`,
`Active`,
`Group_ID`,
`SignUpDate`,
`LastSignIn`
)
VALUES (
NULL, // and that one
'".$db->sql_escape($this->unclean_username)."',
'".$db->sql_escape($this->clean_username)."',
'".$secure_pass."',
'".$db->sql_escape($this->clean_email)."',
'".$this->activation_token."',
'".time()."',
'0', // later, I would also try using an int for an int
'".$this->user_active."',
'1',
'".time()."',
'0'
)";
4) to find another one, better coded, using OOP and PDO.
You given Name as NOT NULL and in Insert statement of your code is not sending Name value, so mysql will throw an exception, saying Name cannot be null, check this once.

Categories