Related
I am making a simple project in ASP.NET and have this code to proceed to login, detect the role and open the exact page.
string cmdText = "SELECT Username,Role FROM Login WHERE Username = '" + TextBox1.Text + "' AND Password = '" + TextBox2.Text + "'";
string username = "";
string role = "";
using (SqlCommand SelectCommand = new SqlCommand(cmdText, connectionstring))
{
SqlDataReader myReader;
connectionstring.Open();
myReader = SelectCommand.ExecuteReader();
while (myReader.Read())
{
username = myReader["Username"].ToString();
role = myReader["Role"].ToString();
}
myReader.Close();
Response.Redirect(role + ".aspx");
}
I set it role+".aspx" because I was having some weird error with the if function.. it wasn't working properly..
But still was having problem redirecting to the page.. and I notice this
So, confused by this error I decided to check the data in SQL Server, and there is this:
There are 5 white spaces after the role.. I tried to delete them. But after save the data the spaces apear again.. I notice that the same thing is with the name and password
but now there are 9 white spaces.. looks like SQL Server Management Studio is trying to fill the max 10 letters...
Username, password and role are nchar(10) type.. is that the problem?
Should I change to fix that? or it can be done on other way
An nchar column stores its values in a fixed length space. If you declare a column to be of type nchar(10) then your values are all padded with spaces to reach the 10 characters length.
If you can change your schema then change the column to be of nvarchar(10) type and (not sure about it) probably you need to reedit all the values already there.
See What is the difference between char, nchar, varchar, and nvarchar in SQL Server?
If you can't change the schema then you could Trim the results in code
Response.Redirect(role.Trim() + ".aspx");
However, looking at your code, I see a very big problem. You are using the famigerate string concatenation to build your query. This is a well know weakness on code and leads to Sql Injection attacks and to parsing errors.
You should fix ASAP that query using parameters
string cmdText = "SELECT Role FROM Login WHERE Username = #name AND Password = #pass";
// You already know the username
string username = textBox1.Text;
string role = "";
using (SqlCommand SelectCommand = new SqlCommand(cmdText, connectionstring))
{
connectionstring.Open();
SelectCommand.Parameters.Add("#name", SqlDbType.NVarChar).Value = textBox1.Text;
SelectCommand.Parameters.Add("#pass", SqlDbType.NVarChar).Value = textBox2.Text;
using(SqlDataReader myReader = SelectCommand.ExecuteReader())
{
while (myReader.Read())
{
role = myReader["Role"].ToString();
}
}
Response.Redirect(role.Trim() + ".aspx");
}
As a final note, consider that storing passwords in clear text in a database is another security weakness to avoid. A well know good practice is to hash and salt a password before storing it in the database
You should use nvarchar(10) instead of nchar(10). char and nchar will always have a fixed length. So if you store an 'a' in a nchar(10) or char(10) it will get padded to the right with spaces to 10 charachters. If you store it as a nvarchar(10) it will be stored as the length of your string.
Only use nchar and char when the length of the column will always be the same.
After converting from nchar to nvarchar. You should also update the data in your columns so they won't have the trailing spaces anymore. (Do this for all the columns which you wish to convert)
update Login set Role = LTRIM(RTRIM(Role))
You can use trim() in the c# code to prevent %20 (blank space) in the url, It is because the role returned by database is 'admin____' (____ = blank space) and not 'admin', There are two options,
1. string cmdText = "SELECT Username,LTrim(RTrim(Role)) FROM Login WHERE Username = '" + TextBox1.Text + "' AND Password = '" + TextBox2.Text + "'";
(or)
2. Response.Redirect(role.trim() + ".aspx");
I have a problem with executing a sql command to the DB. The command should add a new user to the 'users' table.
But when I run the code, I get this Exception on:
command.ExecuteNonQuery();
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.OleDb.OleDbException: Syntax error in INSERT INTO statement.
this is the code of the page - GetSignIn.cshtml :
#{
string Uname = Request["name"];
string userName = Request["userName"];
string pass = Request["passWord"];
string pic = Request["pic"];
string privacy = Request["privacy"];
if(pic == null)
{
pic = "Shared/defaultPic.jpg";
}
System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection();
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Etay\Documents\Visual Studio 2012\WebSites\Josef\Shared\users.mdb";
try
{
System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand();
command.Connection = connection;
connection.Open();
command.CommandText = "INSERT INTO users (userName,passWord,Uname,pic) VALUES ('" + userName + "', '" + pass + "', '" + Uname + "', '" + pass + "', " + pic + ")";
command.ExecuteNonQuery();
Response.Redirect("../HtmlPage.html");
}
finally
{
connection.Close();
}
}
What should I change in my code? Why is it happening? Where is the syntax error in the INSERT INTO?
Use parameterized queries. Here is your statement rewritten to make use of them.
I replaced your try/finally with a using block although your try/finally was acceptable.
Parameterized queries prevent errors and Sql Injection Attacks. An error could occur in your existing code if I were to submit a tick as a part of my user name or password. In the current form this would result in an exception. This is because the tick character is used to quote strings in sql syntax.
using (System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection())
{
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Etay\Documents\Visual Studio 2012\WebSites\Josef\Shared\users.mdb";
using (System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand())
{
command.Connection = connection;
command.CommandText = "INSERT INTO users (userName,passWord,Uname,pic) VALUES (?,?,?,?)";
command.Parameters.Add(userName);
command.Parameters.Add(pass);
command.Parameters.Add(Uname);
command.Parameters.Add(pic);
connection.Open();
command.ExecuteNonQuery();
}
}
About parameters for an OleDb connection from OleDbCommand.Parameters
Remarks
The OLE DB .NET Provider does not support named parameters for passing parameters to an SQL statement or a stored procedure called by an OleDbCommand when CommandType is set to Text. In this case, the question mark (?) placeholder must be used. For example:
SELECT * FROM Customers WHERE CustomerID = ?
Therefore, the order in which OleDbParameter objects are added to the OleDbParameterCollection must directly correspond to the position of the question mark placeholder for the parameter in the command text.
What should I change in my code?
Change to parameters (that also fixes the problem that you don;t have quotes around the pic value)
Remove the second instance of pass in your values
command.CommandText = "INSERT INTO users (userName,passWord,Uname,pic) VALUES (#userName, #pass, #Uname, #pic)";
command.Parameters.Add("#userName").Value = userName;
.. etc.
It's unclear what the type if pic is - you are passing a string but I can;t tell of the column stores a file path or if you are indending to serialize the file and store it in a pinary field.
You set 4 fields after the "INTO" clause, however you're passing 5 parameters:
"INSERT INTO users (userName,passWord,Uname,pic) VALUES ('" + userName + "', '" + pass + "', '" + Uname + "', '" + pass + "', " + pic + ")";
Just add the fifth field, or remove one parameter from the VALUES part
Please check take a look at your Insert statement, it looks like that you provided password value twice.
The number of query values and the destination fields should be same in an INSERT statement.
You have the wrong number parameters in your insert statement. For clarity, why not use string.Format to keep everything uniform? (Assuming these are all string types)
var rawSql = #"Insert INTO Users (userName,passWord,Uname,pic) VALUES ('{0}','{1}','{2}','{3}')";
command.CommandText = string.Format(rawSql, userName, pass, Uname, pic);
command.ExecuteNonQuery();
However, it also looks like you probably want to include that 5th parameter as well - just extend the format :
var rawSql = #"Insert INTO Users (userName,passWord,Uname,pic, privacy) VALUES ('{0}','{1}','{2}','{3}','{4}')";
command.CommandText = string.Format(rawSql, userName, pass, Uname, pic, privacy);
command.ExecuteNonQuery();
Since most of the answers failed to address the SQL Injection vulnerability, here's an example with parameterized queries. In addition to preventing SQL Injection attacks, it also makes it easier to troubleshoot these types of issues, and you don't need to worry about quoting or not quoting parameters.
System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection();
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Etay\Documents\Visual Studio 2012\WebSites\Josef\Shared\users.mdb";
try
{
System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand();
command.Connection = connection;
connection.Open();
command.CommandText = "INSERT INTO users (userName, passWord, Uname, pic, privacy) VALUES (?, ?, ?, ?, ?)";
command.Parameters.Add(userName);
command.Parameters.Add(pass);
command.Parameters.Add(name);
command.Parameters.Add(pic);
command.Parameters.Add(privacy);
command.ExecuteNonQuery();
Response.Redirect("../HtmlPage.html");
}
finally
{
connection.Close();
}
Tnx 4 the help
It happend to be a problem with the database - you can not apply a INSERT INTO statement where the column name is "password". "password" is a Reserved word
in SQL.
Tnx again,
Etay
This is my password textbox aspx elements:
<label for="password">Password</label>
<asp:Text Box ID="User Password" runat ="server" Text Mode ="Password" ></asp:Text Box>
This is my code behind
protected void LoginSubmit_Click(object sender, EventArgs e)
{
BOL ObjectBOL = new BOL();
BAL ObjectBAL = new BAL();
ObjectBOL.UserName_value = UserText.Text;
ObjectBOL.UserPassword_value = UserPassword.Text;
try
{
String Login = ObjectBAL.LoginBAL(ObjectBOL);
int i = int.Parse(Login);
if (i > 0)
{
Response.Redirect("dashboard.aspx", false);
}
else
{
//UserText.Text = "";
//UserPassword.Text = "";
lblMsg.Text = (" Login Failed.... Try Again...");
}
}
catch (Exception LoginException)
{
throw LoginException;
}
finally
{
ObjectBAL = null;
}
}
When the user enters the password in upper case or lower case letters it was accepting the value and redirecting to the next page.
SqlCommand cmd = new SqlCommand ("select count (*) from UserTable where User_Name='" + Login.UserName_value +
"'and User_Password='" + Login.UserPassword_value + "'", con);
string str = cmd.ExecuteScalar().ToString();
return str;
There are two solution for this problem
Change your database table nature .By default SQL server do the case insensitive comparison you need to alter your db table.
ALTER TABLE UserTable
ALTER COLUMN User_Password VARCHAR(20)
COLLATE Latin1_General_CS_AS
Or you can append COLLATE Latin1_General_CS_AS to every query at last without altering your table.
Latin1_General_CS_AS is for case sensitive and Latin1_General_CI_AS for case insensitive comparison
how to make case sensitive comparison in SQL Server
Or you can convert your password in binary then store in db and compare binary content from db and user entered password.
Suggestion
You can go with first solution it will take less time. but second solution is more secure then first one. Do read about this on google. you will find the cons of the directly storing password in plain text.
As mentioned in comment your code is vulnerable to SQL Injection attack. Use parametrize query instead.
Update your SQL Command query with COLLATE Latin1_General_CS_AS as mentioned below to compare string with case sensitive:
SqlCommand cmd = new SqlCommand ("select count (*) from UserTable where User_Name='" + Login.UserName_value +
"' and User_Password='" + Login.UserPassword_value + "' COLLATE Latin1_General_CS_AS", con);
string str = cmd.ExecuteScalar().ToString();
return str;
So I see a couple issues here that you should really look at, let me address those then I'll help with the question you asked.
First, as mentioned in the comments by #Erik Philips, you should be using parameterized queries rather than string concatenation.
Second, you really should be hashing your passwords using a strong hashing algorithm, so if/when your DB gets compromised, you don't divulge all your user's passwords to the attacker.
Ok, as for the actual question at hand you have two options. The far more common solution I've seen is to do the Select just based on the user name, then compare the hashed passwords in C# code to determine whether the user should be logged in or not.
The other option would be to use a case sensitive query in SQL, which in SQL Server requires you to assign a collation via the COLLATE command (either to the query or to the column), perhaps assigning it to whichever relevant character set you want: http://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx
You need to change your sql query only. no need to change table nature and anything else.
SqlCommand cmd = new SqlCommand ("select count(*) from UserTable where User_Name COLLATE Latin1_general_CS_AS ='" + Login.UserName_value + "'and User_Password COLLATE Latin1_general_CS_AS ='" + Login.UserPassword_value + "'", con);
con.Open();
string str = cmd.ExecuteScalar().ToString();
con.Close();
return str;
SqlCommand cmd = new SqlCommand ("select COUNT(*) from UserTable where (CAST(User_Name as varbinary(50))=cast('"+ Login.UserName_value+"' as varbinary)) and (CAST(User_Password as varbinary(50))=cast('"+Login.UserPassword_value+"' as varbinary)),con);
con.Open();
string str = cmd.ExecuteScalar().ToString();
con.Close();
return str;
try this this will work
Please refer the below link, I think as mentioned above collate is the way to go about.
http://www.mytecbits.com/microsoft/sql-server/case-sensitive-search-fetching-lowercase-or-uppercase-string
I have a website where users can log in. The client wants there to be a way to record the number of times any particular user logs in. I have a "Counter" row in the table. How do I program the app (built in C# ASP.NET) to update the counter when people log in? Is this code correct:
cmd.ExecuteNonQuery = "UPDATE Counter FROM brokercenter"
I just recently graduated (as in the 10th of this month) so I am new to this, plus I know nothing about databases, I am just learning on the job. Please let me know if I need any other parameter or connection string or aything else? This is in the button click event and there is already a connection string there to check the username and password so I don't think I need another connection string, but I don;t know for sure. Thanks in advance!
For that matter, here is the whole event (the login stuff works fine, just the update is my question):
string connectionString =
ConfigurationManager.ConnectionStrings["moverschoiceConnectionString"].ConnectionString;
OdbcConnection conn = new OdbcConnection(connectionString);
conn.Open(); OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn;
cmd.CommandText = "select Email, Password from brokercenter where Email = '" + txtLoginEmail.Text + "'";
OdbcDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
if (reader["Password"].ToString() == txtLoginPassword.Text)
{
reader.Close();
if (cbRememberMe.Checked == true)
{
Response.Cookies["username"].Value = txtLoginEmail.Text;
Response.Cookies["username"].Expires = DateTime.Now.AddMonths(1);
Response.Cookies["password"].Value = txtLoginPassword.Text;
Response.Cookies["password"].Expires = DateTime.Now.AddMonths(1);
}
else
{
Response.Cookies["username"].Expires = DateTime.Now.AddMonths(-1);
Response.Cookies["password"].Expires = DateTime.Now.AddMonths(-1);
}
Response.Redirect("BrokerResources.aspx");
}
else
{
lblLoginError.Text = "Invalid Password";
}
}
lblLoginError.Text = "Invalid Email or Password";
reader.Close();
cmd.ExecuteNonQuery = "UPDATE counter FROM brokercenter";
}
For a start, you should read about using UPDATE in MySQL's Reference Manual.
There is even an example for exactly what you want to do.
Quote from the link:
If you access a column from the table to be updated in an expression,
UPDATE uses the current value of the column. For example, the
following statement sets col1 to one more than its current value:
UPDATE t1 SET col1 = col1 + 1;
This is basically all you need, you just need to add a WHERE clause and filter for the username or for the email.
Plus, you should read about SQL Injection because of this:
where Email = '" + txtLoginEmail.Text + "'";
Concatenating strings like this to pass parameters can cause problems as described in the link.
Here's an example how to do it better.
cmd.ExecuteNonQuery = String.Format("UPDATE brokercenter SET counter = {0} WHERE Email = {1}", myCounter++, txtLoginEmail.Text);
where "myCounter" is a local counter variable (which should also be read from the database). Does this make sense now?
I have been working on this school assignment and have gotten to a point at which I have been stuck for a few days now. My ASP.net web page is supposed to allow the user to create an account and login. However, no matter how many times I fill in the Create Account form, it doesn't seem to get added to the database.
Here is my User class, which holds the createAccount Method
public class Userr
{
//Constructor for the Account Creation method(createAccount)
public string createAccount(string strFname, string strLname, string strUname, string address, string city, string state, string phone, string zip, string email,string password)
{
string i="";
string storedProcText = ("INSERT INTO User Values('#ID," +strUname +"','"+strFname +"','"+ strLname +"','"+address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password );
ArrayList parms = null;
DataAccess dataAccess = new DataAccess();
int result = dataAccess.insertUpdateData(parms,storedProcText );
i =result.ToString();
return i;
}
public string Login(string strUsername, string strPassword)
{
DataAccess objDA = new DataAccess();
int result = objDA.LoginUser(strUsername, strPassword);
}
}
Here is my method for updating(stored in the dataAccess object/class
//Constructor for the update method
public int insertUpdateData(ArrayList items, String strProcedureName)
{
int i = 0;
string strConn = WebConfigurationManager.ConnectionStrings["TicketsConnectionString"].ConnectionString;
SqlConnection myConnection = new SqlConnection(strConn);
string sqlText = strProcedureName;
SqlCommand myCommand = new SqlCommand(sqlText);
myCommand.Connection = myConnection;
myCommand.CommandType = CommandType.StoredProcedure;
try
{
using (myConnection)
{
myConnection.Open();
i = myCommand.ExecuteNonQuery();
//grdData.DataSource = myReader;
// grdData.DataBind();
}
}
catch (Exception err)
{
}
return i;
}
The User table contains the follwing fields in order: ID, UserID, FirstName,LastName, Address, City, State, Zip,Phone,EmailAddress,Password
Is my SQL statement wrong, or what? I am at the end of my rope here.
So, off the bat, I see a few issues:
You set your myCommand.CommandType = CommandType.StoredProcedure but, the syntax you provided is not a stored proc. A stored proc would take a name value list of params, which is null in your case.
Lets say you didn't mean to use stored procs, in which case, your sql syntax is incorrect. You don't need the #ID parameter, unless you are passing it in (in which case, you didn't set it). It should be something like this (without knowing the structure of your table):
string storedProcText = ("INSERT INTO User Values("'" +strUname +"','"+strFname +"','"+ strLname +"','" + address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password + "'");
This is given that the values you are inserting matches your table exactly. If not, you will need to specify the table field names in your query as well, like so:
string storedProcText = ("INSERT INTO User(username, firstName, lastName, field4, field5, field6) Values("'" +strUname +"','"+strFname +"','"+ strLname +"','" + address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password + "'");
The way to do this using stored procs is this:
SqlParameter[] parameters = {
new SqlParameter("#param1", SqlDbType.NVarChar, 50),
new SqlParameter("#param2", SqlDbType.VarChar, 100),
new SqlParameter("#param3", SqlDbType.VarChar, 100),
new SqlParameter("#param4", SqlDbType.VarChar, 100),
new SqlParameter("#param5", SqlDbType.VarChar, 100),
new SqlParameter("#param6", SqlDbType.VarChar, 100)
};
parameters[0].Value = strFname;
parameters[1].Value = strLname;
.........
.........
[all the parameters you need]
You need to create a stored proc, also (obviously)
And then you call your dataaccess layer just like you are doing.
Steps for making this work:
1) Don't catch and swallow every exception. The exception will tell you what you are doing wrong here.
2) As Caspar Kleijne points out, you need to put the password in quotes.
3) As I point out, you need to add a parenthesis.
4) You should also use parameterized SQL queries
5) You probably shouldn't be passing the ID,
Here's the corrected SQL string for #2 and #3:
string storedProcText = ("INSERT INTO User Values('#ID,"
+strUname +"','"+strFname +"','"
+ strLname +"','"+address +"','"
+city +"','"+state+"','"
+zip+"','"+phone+"','"
+ email +"','"+ password
+"')" );
It'll take some refactoring to use parameterized queries, and this is a homework project, so I'll leave that as an exercise for you.
So, to start from the beginning, have you stepped through this code with the debugger and determined if it's throwing an exception or returning zero rows modified?
The most worrisome thing is the insertion of the #ID column. If this is an Identity column you shouldn't be inserting this value. If it's not, I don't see you assigning a value to it anywhere.
EDIT:
So as has been mentioned by others here you have some structural issues in you query.
I took your code and threw it in a quick project and here's what your statement looks like.
INSERT INTO User Values('#ID,UserName','FirstName','LastName','123 Some Street','SomeTown','State','54555','555-444-3333','email#email.com','ITS_A_SECRET!
Notice the end of the query. The password field isn't escaped with a closing ' and the param list is not closed with a closing bracket.
A second problem is that #Id field. Is your column in the database an identity field? (It should be) If so, just remove that.
Now, here's the real kicker. Is your table name User? That's a reserved word in SQL server so you'll get errors in your query as is. Format you query like the following and it will work.
string storedProcText = ("INSERT INTO [dbo].[User] Values('" + strUname + "','" + strFname + "','" + strLname + "','" + address + "','" + city + "','" + state + "','" + zip + "','" + phone + "','" + email + "','" + password + "')");
The other issue, as mentioned is that you have the command type set to Stored Procedure when you are not using one.
Modifying you command type to text:
myCommand.CommandType = CommandType.Text;
After I made these modifications and ran your code I ended up with a record in the database.
The most important thing to check right now is that ID field. Is it an identity column? Make sure it is and then remove it from your statement.
In the insert you are trying to insert #ID which first of all most likely would be an identity column, and unless you set IDENTITY_INSERT ON on that table, will throw an exception, second, even if it was not an identity column, you are not providing the parameter definition for the #ID parameter to the command.
Try removing #ID from the insert statement, and pass in everything else, but ID.
As a side note, your SQL Statement is prone to SQL Injection attacks since you're concatenating sql command string and values provided by user into one string. I would recommend using parameters instead the actual values and then adding parameters to the sql command later.
I cannot post everything as a comment , but can you do one thing..
put a break point and take the contents of this string
string storedProcText = ("INSERT INTO User Values('#ID," +strUname +"','"+strFname +"','"+ strLname +"','"+address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password );
and paste the value of storeProcText directly in the database and see if it can successfuly run and create a record for you.
break and debug should fix your problem
Please Comment out this statement:
myCommand.CommandType = CommandType.StoredProcedure’;
You can use a sql script directly.