SQL Server - How to insert a hashed password to a table? - sql

Sorry for my ignorance, but I want to store hashed password in my database,
How can use the HASHBYTES method to store hashed password in Users table ?
CREATE TABLE [Users](
EmailAddress NVARCHAR(320) UNIQUE,
UserID INT IDENTITY(1,1) PRIMARY KEY,
UserPassword NVARCHAR(32), -- I Edited the length
FirstName VARCHAR(256) not null,
LastName VARCHAR(256) not null,
MobileNumber BIGINT,
)
--I checked and found this is how to hash a password
declare #afterhash varbinary(256) = HASHBYTES('SHA2_256', 'P#ssw0rd')
But how do I combine them both ?

As mentioned, I don't understand the problem here. Just use HASHBYTES in your parametrised INSERT:
INSERT INTO dbo.Users (EmailAddress, UserPassword, FirstName, LastName, MobileNumber)
VALUES(#EmailAddress, HASHBYTES('SHA2_256',#Password), #FirstName, #LastName, #MobileNumber);
Side Note: As I mentioned in my other answer, bigint isn't the right choice for a telephone number. Phone Numbers can start with a 0 and contain other characters from digits. A value like '01234567890' would be changed to 1234567890, a number like '+441234567890' would be changed to 441234567890, and a number like '(01234) 567890' would fail to INSERT completely

declare #Users table (passwordColumn NVARCHAR(32));
insert #Users values (HASHBYTES('SHA2_256','Password#1234.'));
select HASHBYTES('SHA2_256', passwordColumn) from #Users;

Related

To Find and Eliminate the Duplicates

I use this code to update one of my table by calling a function which generates a random ID each item. I started with around 1000 rows but now the size is growing and i find that there are duplicate ID's in the table. Is there any way to can modify the code i am using, so that it look for ID's that are already generated in the table so that it will generate a new code if there is a similar one. I also noticed
Your code shows you setting the field password, but the results show that UniqueID is the duplicated field. (Maybe it's password renamed?)
Assuming userId is unique: (if not, ADD an actual identity column NOW, "ALTER TABLE dbo.Users ADD ID INT NOT NULL IDENTITY(1, 1)" should do the trick) and assuming password is the field to change, use the following:
DECLARE #FN VARCHAR(20);
DECLARE #LN VARCHAR(20);
DECLARE #PW VARCHAR(20);
DECLARE #ID INT;
SELECT TOP 1
#FN = FirstName,
#LN = LastName,
#ID = userID
FROM dbo.Users
WHERE Password IS NULL;
WHILE ##ROWCOUNT = 1
BEGIN
SET #PW = dbo.GenerateID(FirstName, LastName);
WHILE EXIST (SELECT TOP 1 Password FROM dbo.Users WHERE Password = #PW)
SET #PW = dbo.GenerateID(FirstName, LastName);
UPDATE dbo.Users SET Password = #PW WHERE userId = #ID;
SELECT TOP 1
#FN = FirstName,
#LN = LastName,
#ID = userID
FROM dbo.Users
WHERE Password IS NULL;
END
This should look for a blank password. If none is found the outer loop is skipped. If one is found, we generate passwords until we find one not in the table. Next we look for another row with a blank password before the end of the outer loop.
Sounds like your new to this. Don't worry, TSQL is pretty easy to learn. First thing first, I suggest that you create a unique non-clustered index on the UniqueID column--this will prevent duplicates values from being inserted into your table. If someone does try to insert a duplicate value into the table it will throw an exception. Before you can use this though you'll need to remove all the duplicate 'UniqueID' values from your table.
CREATE UNIQUE NONCLUSTERED INDEX [IDX_UniqueID] ON [dbo].[Users]
(
[UniqueID] ASC
) ON [PRIMARY]
You can learn more about non-clustered indexes here: https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described
I also suggest that you consider changing the underlying type of your UniqueID field to a 'uniqueidentifier.' Here's an example of a table schema that uses a 'uniqueidentifier' column type for the UniqueID column:
CREATE TABLE [dbo].[Users](
[personId] [int] IDENTITY(1,1) NOT NULL,
[firstName] [nvarchar](50) NOT NULL,
[lastName] [nvarchar](50) NOT NULL,
[UniqueID] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[personId] ASC
) ON [PRIMARY]
) ON [PRIMARY]
A 'uniqueidentifier' column type in SQL Serever holds a Global Unique Identifier (aka a GUID or UUID). It's easy to generate a GUID in most languages. To generate a GUID in TSQL you just new to invoke the NEWID() function.
SELECT NEWID() -- output: D100FC00-B482-4580-A161-199BE264C1D1
You can learn more about GUIDs here: https://en.wikipedia.org/wiki/Universally_unique_identifier
Hope this helps. Best of luck on your project. :)

Automatic user signature in SQL

Trying to add the user name to a table, but I get dbo as user name
CREATE TABLE username
(
ID int,
Date datetime default CURRENT_TIMESTAMP,
Signatur varchar(200) default CURRENT_USER,
Comment varchar(255),
);
AND THEN
INSERT INTO username
(Comment)
VALUES
('Just some text');
SELECT * FROM username
ORDER BY Date desc;
result
When I replace CURRENT_USER with SYSTEM_USER or SUSER_SNAME() I get the user name DESKTOP-0DM0L90\jokr1
How do I get only jokr1 as user name?
The full username is domain\user; so that's what all of the user/suser etc. commands give you. You can use standard string manipulation techniques to get just one part of the string.
CREATE TABLE username
(
ID int,
Date datetime default CURRENT_TIMESTAMP,
Signatur varchar(200) default right(SYSTEM_USER,len(SYSTEM_USER)-charindex('\',SYSTEM_USER)),
Comment varchar(255),
);
If you ever want to identify the 'user' associated with this, I would recommend storing the SID via:
SELECT SUSER_SID(system_user)

Using Salts in Hashing

Say I have a table like this:
create table [User] (ID int identity not null,EmailAddress varchar(50), [Password] nvarchar(128),primary key (ID))
My reading is telling me that I should add a salt to the table:
alter table [user] add salt nvarchar(128)
If a user creates an account in the application then I believe the SQL should be as follows:
declare #RandomNumber as varchar(32)
set #RandomNumber=rand();
insert into [user] (emailaddress,[password],salt) values ('test#hotmail.co.uk',hashbytes('sha2_256','passwordvalue' + #RandomNumber),#RandomNumber)
Then lets say the user wants to authenticate. The SQL would be like this:
select * from [user] where [password] = hashbytes('sha2_256','passwordvalue' + salt)
The last SQL statement returns nothing, which proves it is incorrect.
Use varchar and not nvarchar, there convertion probleme or declare #RandomNumber as nvarchar(32) like this:
declare #RandomNumber as nvarchar(32)
set #RandomNumber=rand();
insert into [user] (emailaddress,[password],salt) values ('test#hotmail.co.uk',hashbytes('sha2_256','passwordvalue' + #RandomNumber),#RandomNumber)

Inserting record from one column to another column in the same scope or statement

I have a Stored Procedure that populates a table: This table as indicated in the code below has an identity column which is also the primary key column.
I would like to append the primary key to contain leading letters: Example: ABC123.
Obviously this is not possible because the Primary key column is INT datatype.
So I created an additional column so that I can insert the appended primary key. This works except I have to make the new column Null and I am using an UPDATE statement.
Something tells me there is a better way.
Is there a way I can do this without using UPDATE after the initial Insert and have the new column CategoryID as Not Null?
Table Code:
CREATE TABLE [dbo].[Registration] (
[SystemID] INT IDENTITY (100035891, 1) NOT NULL,
[CategoryID] CHAR (13) NULL,
[FName] VARCHAR (30) NOT NULL,
[LName] VARCHAR (30) NOT NULL,
[MInit] CHAR (1) NULL,
PRIMARY KEY CLUSTERED ([SystemID] ASC)
);
Stored Procedure:
CREATE PROCEDURE [dbo].[uspInsertRegistration]
#FName VARCHAR(30),
#LName VARCHAR(30),
#MInit CHAR(1),
#CategoryID CHAR(13),
#SystemID int OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #ErrCode int
INSERT INTO [dbo].[Registration] ([FName],[LName],[MInit])
VALUES (#FName, #LName, #MInit)
SELECT #ErrCode = ##ERROR, #SystemID = SCOPE_IDENTITY()
UPDATE [dbo].[Registration]
SET CategoryID = 'ABC'+ CAST(SystemID AS CHAR)
SET NOCOUNT OFF
RETURN #ErrCode
END
Finally this is what the table looks like with the data:
Thanks for being contagious with your knowledge. :)
Guy
My suggestion is to use a computed column, as what you're trying to do introduces redundancy. See below:
http://msdn.microsoft.com/en-us/library/ms191250%28v=sql.105%29.aspx
Alternately, make it big enough to contain a GUID, put a GUID into the column on the insert, then update it afterwards.

Foreign Key is null when insert using Stored Procedure

I've created a insert stored procedure with two tables like in the exapmle:
Table NameAge
CREATE TABLE [dbo].[Assignment3_NameAge]
(
userID int PRIMARY KEY IDENTITY(1,1),
Name varchar(255) NOT NULL,
Age int NOT NULL
)
Table Hobbies
CREATE TABLE [dbo].[Assignment3_Hobbies]
(
hobbiesID int Identity(1,1) Primary Key,
userID int Foreign Key references Assignment3_NameAge(userID),
hobbies varchar(255) NOT NULL,
)
Insert Stored Procedure
CREATE PROCEDURE [dbo].p_Assignment3Join_ins
#Name nvarchar(100),
#Age int,
#Hobbies nvarchar(100)
AS
INSERT INTO [TABLE].[dbo].[Assignment3_NameAge]
([Name]
,[Age])
VALUES (#Name,#Age)
INSERT INTO [TABLE].[dbo].[Assignment3_Hobbies]
([Hobbies])
VALUES (#Hobbies)
The problem is that when i run the stored procedure the table Hobbies has a null value for userid(the foreign key)
What am i doing wrong?
You should provide the key of the Assignment3_NameAge value you want to insert into Assignment3_Hobbies.
If you want the last inserted you can use SCOPE_IDENTITY() from SQL Server(if you're using SQL Server) or equivalent. It will give you the last inserted value from Assignment3_NameAge
I am guessing this is SQL Server based on the IDENTITY column. Correct?
The first insert creates a user, but there is no user ID being set on the insert of the hobby. You need to capture the identity value from the first insert to be used in the second insert. Have you gon over the system functions available?
You're not supplying a value for it, SQL won't automagically fill the value in for you even though you've created a Foreign Key relationship. It's your job to populate the tables.