Hi everyone I want make sure the username is unique!
First I get there username and check if existing already. If not add them to the database, but if the username is taken I will add number behind it.
Example: JoshSmith, JoshSmith1
If there is no username the user still use the id version. I will get there first and last name. And then repeat the above steps.
The problem: If JoshSmith is taken I will add number behind it, but if JoshSmith1 is also taken.
If I use
SELECT count(*) FROM users WHERE username LIKE '%JoshSmith%'
it will return names like JoshSmithing and this is wrong. If I use
MATCH () AGAINST ()
returns the same results.
First I thought to count how many times the username exist and add the number+1
JoshSmith14
But that will be wrong.
You can use regular expressions to filter JoshSmith[numbers] and find biggest number. But, as for me, this is bad way, as you will have a lot of loading to your DB server. I think that it would be better to store counts in some table (especially if correct numbers are important to you).
Related
I am looking for the best way to write out a php/mysql query to create unique user id's rather than using the autoincrement method in mysql.
Ex: Facebook gives users a long string of numbers as a user id when singing up before you can assign a username. This string of numbers can be used to view your profile OR you can use username. I want users to be able to change username in the future, so don't want to design my system based on username.
I don't know how big the site will get, so please take that into consideration with the solution. I don't want something that is going to be server intensive if there are alot of users signing up.
There isn't really a best route for something like this. Essentially you need to ask yourself what your system requires. You may be able to use an email address as the ID, an auto-incremented number, MD5 hash, or even a heavy-entropy GUID.
Keep in mind that email addresses may change, auto-incremented numbers can be leveraged in automated exploits, and there's technically some chance of hashes colliding.
If you decided to go the route of generating a high-entropy GUID using PHP, you could do so using a function like uniqid.
echo uniqid(); // 513ac40699d85
echo uniqid("_", true); // _513ac3e00bfe46.78760239
The second line shows the two arguments you can provide; a prefix, and a request for more entropy, which will result in a more unique result.
You should follow some algorithm like this:
Enter your new user into the database.
Get the record ID
Generate the userID
Insert the userID next to the name into the sql database.
Enter your new user into the database.
//get username from previous form
$user=$_POST['user'];
// login into mysql server and prepare data for writing
$connect=mysql_connect('localhost', $user, $pass);
$selectdb = mysql_select_db('mydb');
$query = "insert into users_table set
username='$user';";
$run_query=mysql_query($query);
Get the record ID
$id=mysql_insert_id();
Generate the userID
$first_chars=substr($user, 2);
$year=date('y');
$new_user_id= $first_chars.$year.$id;
Insert the UserID next to the name into the sql database
$query="update users_table set userid='$new_user_id' where id='$id';";
$run_query=mysql_query($query);
if (!$run_query) {
echo mysql_error();
}
else {
echo 'your user name is '.$user.' and user id is '.$new_user_id ; }
You can use mysql as a database. Wampserver combines everything and makes it easy. However, i'm not sure if I can help you very much because your question is very vague. Add some more detail please.
Use a hexdigest like sha or md5 to generate an id something like sha1($uname+$timestamp+$salt)
By doing this your will be storing a lot of data for each entry as sha1 takes up 40 bytes.You have already mentioned that the site is may go big,making it a huge amount of data.Decide whether its worth that lot of space.
PS:you can always slice the string,but the collision chance is more that way.
I've been dabbling abit with a login script (PHP and MySQL), using various online tutorials. Today I became curious as to which way is the best to check if a username and password is valid. Every tutorial I've read so far checks the number of row returned, like this:
SELECT stuff FROM users WHERE username = input_username AND password = input_password
count the rows returned
if rows equal to one
login
else
display error message
I was just thinking if it's equally viable to use COUNT and check that value instead, like this:
SELECT COUNT(stuff) FROM users WHERE username = input_username AND password = input_password
if returned value equal to one
login
else
display error message
I've tried both and both work return the intended result. So is there any reason to choose one over the other?
They are both valid approaches. You would use the former when you needed additional info about the user, e.g., their UserID.
You should definitely go with second SQL-statement if you don't need any of the information stored. COUNT() is better for performance. Although the reason people tend to stick to the first one is because they will be needing information about the user if rows returned is positive.
Problem Overview:
My application has an enrollment form.
Users have a habit of entering the same person into the system twice.
I need to find a way to rapidly and accurately check the data they've entered against the other clients in the database to see if that client is already in the database.
Criteria Currently Being Used:
Duplicate SSN
Duplicate Last Name and Date of Birth
Duplicate First Name, Date Of Birth and Partial SSN Match (another client has an SSN where 5 of the 9 digits are the same and in the same position.
Duplicate First Name and Partial SSN Match (another client has an SSN where 5 of the 9 digits are the same and in the same position.
Duplicate Last Name and Partial SSN Match (another client has an SSN where 5 of the 9 digits are the same and in the same position.
In addition to these checks, there's been discussion of using soundex to detect matches based on similiar first name / last name.
Is there a PHP class already designed to handle something like this? Can something like this be done at a (Mysql) Database level?
Clarifications:
The problem exists not because of a lack of data integrity at the database level but because of typos caused during the entry process. The applicaiton is a data-entry application. Users are taking physical paper copies of forms and entering the data into the application.
If I understand your problem correctly the point is that the duplicates you want to filter out are not necessarely equal as strings. I encountered situations like this a couple of times in the past and I could never find a perfect criteria for finding logical duplicates. In my opinion the best way to deal with such cases is to provide a very smart autocomplete-like functionallity to the user, so when he tries to enter the data he sees all the similar entries and he hopefully won't create a new entry for something he see in the list. Such a soulution can be a good "buddy" of your not-yet-perfect criteria.
Not a php solution, but
You can cast that fields in your database as unique.
ALTER TABLE `users` ADD UNIQUE (
`username`
)
Im not even sure if this is possible (Im new to php)
Anyway, what I want to do is this:
mysql_query("SELECT * FROM user_table WHERE concat(username,'#',domain)='$username' LIMIT=1");
Ok, so the $username is an email address that is submitted by a user to search the database to check that they exist. In the user_table usernames are not stored in a single column, they are stored in several with the domain and the actual username being separate.
for example username could be bob and the domain could be website.com.au
Then when the user wants to search for that user the type in bob#website.com.au
This goes to the query above.
So, should it work or not? If not how can I make this work or what suggestions do you have for me?
As BobbyJack has mentioned, this is a slow way of locating a user record.
If you cannot store email address in a single column and place an index on that column, split the string in PHP and make your query:
SELECT * FROM user_table WHERE `username` = '$username' AND `domain` = '$domain'
You could then create a unique index combining domain + username so you wouldn't need LIMIT 1
probably worded the question slightly wrong.
Anyway this is what I have done "SELECT * FROM virtual_user WHERE concat_ws('#',username,domain)='$username'"
I no longer need to use the LIMIT=1, I probably never needed to as all results in the table are individual, so it will always only return a limit of 1 or nothing at all.
It isn't slow in my opinion, but then again Im not really sure what to compare it to. We have about 7000+ records it sorts through so yeah. Is there anyway to get it to tell you how long the query took to complete?
I would like to put both the username and domain into just a single indexed field but its for a postfix mail server and I'm not allowed or game to play with the queries it uses. Especially not on a functioning server that actually handles mail.
Let's say I have a SQL statement like this that checks a user login:
SELECT * FROM users
WHERE username='test#example.com', password='abc123', expire_date>=NOW();
Is there a way in SQL to determine specifically which WHERE conditions fail, without having to separate each condition into its own query and test individually?
In this specific example it would allow the developer to tell users exactly the reason why their attempt to login failed.
For my purposes I'm using PHP/MySQL.
Well, one thing you could do is change your query so it only matches on the username. Then in the code you check the password and the expiration date, returning appropriate errors.
Also, I hope your example query is a simplification; Certainly you should be salting/encrypting/hashing your passwords, and you should include something that limits the number of failed attempts within a certain timeframe, etc...
As far as your actual question (as opposed to the results you are looking for), there isn't a way to get that information from the where clause. The closest you could do would be something like:
SELECT *,
CASE WHEN Password = 'asdf' THEN 1 ELSE 0 END AS IsPasswordMatch,
CASE WHEN Expiration >= NOW() THEN 1 ELSE 0 END AS IsActiveAccount
FROM Users
WHERE Username = 'user'
In MySQL you can put boolean expressions in the select-list. Boolean expressions evaluate to the integer 1 when true, or the integer 0 when false.
SELECT password = 'abc123' AS is_authenticated,
expire_date >= NOW() AS is_not_expired
FROM users
WHERE username='test#example.com';
note: If you need to write a query that works on other brands of RDBMS, keep in mind this use of boolean expressions is nonstandard. Use the CASE syntax that other folks have posted.
PS: This is a tangent from your question, but I urge you not to store passwords in plaintext. Store a hash digest of the salted password. See How does password salt help against a rainbow table attack?
No, the where-clause is applied as a block, and various techniques are used so that not all rows have to be scanned. Also, how would you know which row was the one that was desired?
Additionally, you probably don't want to tell the user too much about why a login attempt failed. Saying too much allows for exploits such as account mining and password attacks.
edit If you truly do want to display this to your user, then split your logic into different parts:
Validate identity
Action: Fetch the corresponding user row from the database
Result:
If no such row exist => invalid account
If row is returned, continue to step 2.
Validate credential
Action: Check the stored credential (password, hash of password or encrypted password) against the supplied password treated in the same way the credential is stored.
Result:
No match => Invalid password / credential
Match => Successful login attempt
Login user
Action: Add data to session etc.
You probably just need to separate the parts of the where clause with 'AND'
SELECT * FROM users
WHERE username='test#example.com'
And password='abc123'
And expire_date>=NOW();
Here is what I came up with:
SELECT
IF(mem_username='test#example.com','true','Error: Bad Username') AS mem_username,
IF(mem_password ='abc123','true','Error: Bad Password') AS mem_password'
FROM MEMBERS
WHERE mem_username='test#example.com' AND mem_password='abc123'
This way I can detect in code for error messages and then display them as necessary.
NOTE: To all of you citing security concerns with the example code, thank you for your concern. However, this is not real production code this was simply a simple example to demonstrate the question I had. It is quite obvious that you shouldn't store passwords in clear text, and that you shouldn't give users specifics on why login fails.