User schema for website - php

I need to create a database schema for storing user information (id, name, p/w, email address ...etc). I have always picked arbitrary amounts when sizing these fields. With this said, I have two questions:
1) What are good sizes for these fields? I am sure there is a maximum email address length for example...etc.
2) I now need to store user mailing addresses for credit card purchases, including international mailing addresses. This is an area I do not want to pick arbitrary sizes.
Does anyone know of a good schema for either? Is there a project for this maybe?
Thanks!

Also consider which db engine you will use and whether the primary key will be email, rowid, or an arbitrary number. I typically save passwords on a second table called "security" using a hash as suggested above. Here's an example.
CREATE TABLE IF NOT EXISTS `users` (
`user_id` varchar(255) NOT NULL,
`active` char(1) default 'Y',
`created_date` INTEGER UNSIGNED default 0,
`email` varchar(255) default NULL,
`first_name` varchar(255) default NULL,
`last_name` varchar(255) default NULL,
`modified_date` INTEGER UNSIGNED default 0,
PRIMARY KEY (`user_id`, `active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

I'll give you a hand with part 1. In general you shouldn't stress very much about the size of your MySQL DB fields, you don't have to get the number exactly right -- just make sure that someone with a reasonable answer doesn't get their data truncated.
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255),
`email` varchar(255),
`password` char(256)
Notice that for password I have a 256bit character field instead of a varchar field. Thats because you should never store plain text passwords in a database. Instead, you should always store the password in a hashed format with some sort of unique "salt" for that password. You can find some tutorials online, and the length of the password field depends on the type of hashing you use on the password.

This is a pretty tough question to answer, because in my opinion there is a difference between what you "should" allow and what is considered allowable by the IETF.
The maximum allowable email address is 256 characters which includes a slash at the beginning and end of the email address (therefore only 254 usable characters). You can find detailed information about it on this page by Dominic Sayers.
But will any legitimate user actually have an email address that long?
As for street addresses, I don't believe that is specified anywhere, however according to the world's longest website the longest street name is 72 characters. Therefore if you made the field 100 characters you would have more than enough room for the street address.
You don't have to be really too concerned with getting everything 100% correct, you should be more concerned with the quality of the data which you decide to accept into the database (make sure it is valid/clean). Also provide clear rejection messages if someone does enter something which is simply too long -- and make sure there is an easy method for the owner of the website to be contacted if that does happen.
One thing I'd like to note, NoSQL is all the rage right now, and it uses schema-less database engines, for example MongoDB and CouchDB. It is not the best solution for everything, however if you are very concerned about having the correct schema, possibly a schema-less database might be a good option.

Related

Suggested data types for MySQL table holding user registrations?

I'm writing a site in PHP,
I have come up with these MySQL data types to use in the user registration table. Do these look ok or are there better data types that can be used?
id INT(100)
email VARCHAR(100)
password VARCHAR(100)
nickname VARCHAR(30)
registration_date DATE()
lastlogon_date DATE()
Email is obviously an e-mail address, password is an encrypted string created by PHP password_hash() and nickname is a user chosen nickname that can be up to 30 characters long, but isn't neccasarily 30 characters long.
ThanksJack
Looks fine except your 'id' columns size looks too large. You didnt mention how you were going to create the id's but if you use AI (auto increment) and start a 1 or even 100, INT(100) seems to be an over kill. Think about it, your id starts at 1 & AI to even 10 decimal places or 10,000,000,000 ids. INT(10) or id seems sufficient if you think youll have less than 10 billion users/ids.
Everything else looks good. I hope this helps!

what is the main function of uniqid(”, true)?

I'm studying a login system at http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/.
And I want to ask, what is the main function of uniqid(”, true)?
The tutorial from the website says
"user unique id – I am generating unique user id in php using uniqid(”, true) function. Sample user id will be like 4f074eca601fb8.88015924"
Why it must generate the user id? For security or for what?
Thank you so much guys.
This is the mysql query for my database.
create table users(
uid int(11) primary key auto_increment,
unique_id varchar(23) not null unique,
name varchar(50) not null,
email varchar(100) not null unique,
encrypted_password varchar(80) not null,
salt varchar(10) not null,
created_at datetime,
updated_at datetime null
); /** Creating Users Table **/
Maybe this unique_id is used for data submission. For example, submitting a form with ajax may require the user id of the person submitting it, so to prevent hackers from changing the data sent to the server, unique id are used to make the change almost useless cuz they don't know the pattern of how people are assigned IDs. Another reason, unique id might be useful in, it might be used in the url to show the profile of someone. example: profile.php?id=unique_long_id
This prevents people from knowing how many users exist in the website ...
There is unlimited ways you can be creative with unique ids :)
Usually, something like a "complex" (understand not an auto_increment thing) id is used so that no user can guess an other user's id.
If you used something like the uid (the primary key auto_increment column), it would be easy to guess that users 145th, 146th, ... exist. A user may try to brute force some requests manipulating the id.
In a badly coded website where you don't have any security check before updating a value, let's assume you have this URL to update a password : http://example.com/update_password?uid=150&password=trolling. Easy to change any users password right ? But with the unique_id, it's more complex.
Now why the 2 arguments in uniqid('',true) ? Because from the manual :
/* We can also activate the more_entropy parameter, which is
* required on some systems, like Cygwin. This makes uniqid()
* produce a value like: 4b340550242239.64159797
*/

How do I store a BIGINT in MySQL using PDO?

I know this question has been asked more than once here, but I couldn't find a solution.
We are using a database where we are storing the facebook id as a BIGINT(20).
create table users(
fb_id bigint(20) NOT NULL,
user_name varchar(30) NOT NULL,
CONSTRAINT uk_name unique (user_name),
CONSTRAINT pk_fb_id primary key (fb_id)
)ENGINE=INNODB;
But the PDO engine of PHP can insert only the max integer value of PHP, i.e. 2147483647.
$stmt->bindParam(':fb_id', $this->fb_id, PDO::PARAM_INT);
This, I understand, is quite obvious since we are limited by the maximum value of integer in PHP. I tried to use the string -
$stmt->bindParam(':fb_id', $this->fb_id, PDO::PARAM_STR);
but still it doesn't work.
I want to know if there could be a workaround to store it as bigint.
We are using a database where we are storing the facebook id as a BIGINT(20).
Why oh why are you doing that?
I think general consensus is that Facebook ids should not be saved as numeric types, but as strings instead. Saving them as something numeric does not yield any advantages whatsoever – but several disadvantages.

How to replicate password hash for provided password and salt (PHP/MySQL)

Password needs to be matched by Password Hash which was originally created on a .NET platform and stored on MSSQL (so encryption is probably SHA1).
Here is how MySQL table looks like:
CREATE TABLE IF NOT EXISTS `test` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`UserName` varchar(100) COLLATE latin1_general_ci DEFAULT NULL,
`PasswordHash` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
`PasswordSalt` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=12535 ;
--
-- Dumping data for table `test`
--
INSERT INTO `test` (`id`, `UserName`, `PasswordHash`, `PasswordSalt`) VALUES(9836, 'demoadmin', '?z1??9t|????e&??9aK', -1190254076);
INSERT INTO `test` (`id`, `UserName`, `PasswordHash`, `PasswordSalt`) VALUES(12534, 'sunny', '??o\\(R?8~??6>?t????o', 549612932);
I've found two very close examples to what I need to be done but I was enable to make it work.
Example 1: http://gilbert.pellegrom.me/replicating-net-password-hashing-in-php/
Example 2: http://www.kevinbruce.com/Blog?area_id=6&blog_id=3&ba_id=27
Usernames and passwords are:
First user: demoadmin/demotest
Second user: sunny/eclyptix
Please help!
It looks like you have an encoding problem:
'?z1??9t|????e&??9aK'
It seems that your original code was broken and was converting characters out of the printable ASCII range into question marks.
You could try to replicate this behaviour in PHP. However continuing to use this broken scheme will compromise the security of your system as it is much more likely that a hash collision can be found. It might be necessary to get all your users to change their passwords. This time make sure that the hashes are stored correctly. You may also want to consider storing them as hexadecimal strings instead of binary data to minimize the risk of further encoding problems.
Kevin Bruce here (from the second example you cited).
For what it's worth, I never got the problem solved with my experience. I actually spoke with Elizabeth Smith (who works on PHP core for Windows) and she agreed that there is a big disconnect in hash support on the same level as .NET, due to character encoding support in PHP. This is what I suspected.

IDs in MySQL, standard IDs or alphanumerics?

I'm thinking of this, if I make a web site for a specific university's students should I make the ID as standard IDs on MySQL (integer, auto increment) or should I give the IDs as how is their email address is, like if the student's email address is e12234#university.edu then his/her id is e12234 (on my web site). Is it ok, what about performance?
Edit: Also, there are such email addresses:
n13345#university.edu (exchange student)
jennajameson#university.edu (this is a professor)
I would strongly recommend a separate, independent value for the id (integer, auto increment). Id values should never change, never be updated. People change their emails all the time, corporations reissue the same email address to new users sometimes.
If an emailaddress is unique and static in your population (and make very sure it is), you may make it a primary key, and actually a full normalization would favor that option. There are however some pitfalls to consider:
People change emailaddresses once in while. What if a student becomes a professor, or is harassed on his/hers emailaddress so he/she applied for a new address and got one? The primary key shold not change, ever, so there goes your schema.
Sanitizing emailaddresses takes a little bit more effort then integers.
Depending on how many foreign keys point to this ID, needed storage space could be increased, and joining on CHARs rather then INTs could suffer in performance (you should test that though)
Generally you'd want to map strings to ids and reference the ID eveywhere
CREATE TABLE `student` (
`id` int unsigned NOT NULL auto_increment,
`email` varchar(150) NOT NULL
PRIMARY KEY (`id`)
)
This will reduce the size of any table reference the email table as it will be using an INT instead of a VARCHAR.
Also if you used part of their email and the user ever changed their email you'd have to go back through every table and update their ID.

Categories