I'm creating a simple web service to authenticate a user.
I have a problem filling the datatable(used to store the results of a select statement) properly, 'dt.rows.count' (dt is the name of the datatable) always returns 0 even if the select statement returns nothing. I've tried clearing the datatable before filling it, and after the if condition as well, but to no avail, I get the same result.
Would really appreciate any advice on how to proceed.
[WebMethod]
public string Authen(string a, string b)
{
var con = new SqlConnection("Data Source=SERVER-SQL;Initial Catalog=DECA-DB;Persist Security Info=True;User ID=sa;Password=*****");
var sda = new SqlDataAdapter("SELECT * FROM Login_Matrix WHERE Username = ' " + a + " ' AND Password = ' " + b + " '", con);
var dt = new DataTable();
con.Open();
dt.Clear();
sda.Fill(dt);
con.Close();
int x = dt.Rows.Count;
//return (x);
if ( x >0)
{
dt.Clear();
return ("In");
}
else
{
dt.Clear();
return ("out");
}
}
}
Adding a space after and before the single quotes makes your query search for inexistant user names and passords (like " Steve ") and it return no records
A quick fix could be
var sda = new SqlDataAdapter(#"SELECT * FROM Login_Matrix
WHERE Username = '" + a + "'
AND Password = '" + b + "'", con);
but this is very dangerous.
This code is vulnerable to Sql Injection attacks.
You should use parameters
var sda = new SqlDataAdapter(#"SELECT * FROM Login_Matrix
WHERE Username = #uname
AND Password = #pwd", con);
sda.SelectCommand.Parameters.Add("#uname", SqlDbType.NVarChar).Value = a;
sda.SelectCommand.Parameters.Add("#pwd", SqlDbType.NVarChar).Value = b;
And on the same line about security, another thing to consider as soon as possible, is that storing plain text password in your database is a really big security risk. You should search how to salt and store an hash of the password
There are other parts of this code to improve.
First you need to have using statements around the disposable objects
like the connection or the command.
Second, there is no need to have a full SqlDataAdapter and a
DataTable to just check if the user exists or not.
So you can rewrite your code as:
string cmdText = #"IF EXISTS(SELECT 1 FROM Login_Matrix
WHERE Username = #uname AND Password = #pwd)
SELECT 1 ELSE SELECT 0";
using(SqlConnection con = new SqlConnection("....."))
using(SqlCommand cmd = new SqlCommand(cmdText, con))
{
con.Open();
int result = (int)cmd.ExecuteScalar();
return ( result == 1 ? "In" : "out");
}
Related
if you can´t open i will try to explain
basically i get this error 'Incorrect syntax near the keyword 'Table'.'
it tells me that it is in te sda.fill(dtbl) where the error occurs
{
SqlConnection sqlcon = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\SQL Database\LOGIN DB.mdf;Integrated Security=True;Connect Timeout=30");
string query = "Select * from dbo.Table Where [Username] = '" + txtUsername.Text.Trim() + "' and [Password] ='" + txtPassword.Text.Trim() + "'";
SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon);
DataTable dtbl = new DataTable();
sda.Fill(dtbl);
if (dtbl.Rows.Count == 1)
{
EntrarConta entrar = new EntrarConta();
entrar.Show();
this.Close();
}
else
{
MessageBox.Show("Check your Username or password");
}
}
this is the code
Its because 'Table' is reserved keyword for T-SQL.
Either change the table name or use square bracket around the [dbo].[Table]
The problem is that Table is reserved word and should be escaped: [Table].
You can put it like this:
//DONE: wrap IDisposable with using
using (SqlConnection sqlcon = new SqlConnection(...)) {
//DONE: make sql readabale and parametrized
string query =
#"select 1
from [dbo].[Table]
where [Username] = #prmUserName
and [Password] = #prmPassword";
using (SqlCommand q = new SqlCommand(query, sqlcon)) {
//TODO: more accurate is to create parameter and then assign the value
q.Parameters.AddWithValue("#prmUserName", txtUsername.Text.Trim());
q.Parameters.AddWithValue("#prmPassword", txtPassword.Text.Trim());
if (q.ExecuteScalar() != null) { // If we've read a record
EntrarConta entrar = new EntrarConta();
entrar.Show();
this.Close();
}
else {
MessageBox.Show("Check your Username or password");
}
}
}
Please, note, that keeping passwords in a table is dangerous (what if the table is stolen?). Much better to put hashes instead of plain text.
I'm trying to implement a password change feature but it doesn't seem to want to work.
private void button3_Click(object sender, EventArgs e)
{
using (OleDbConnection con = new OleDbConnection(#"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = C:\Users\User\Desktop\esoft\gym\gym\bin\Debug\Clients.accdb"))
{
DataTable dt = new DataTable();
con.Open();
errorProvider1.Clear();
if (dt.Rows[0][0].ToString() == "1")
{
if (textBox3.Text == textBox4.Text)
{
OleDbDataAdapter da = new OleDbDataAdapter(" COUNT (*) FROM login WHERE username= '" + textBox1.Text + "' AND [password]='" + textBox2.Text + "' ", con);
OleDbCommand com = new OleDbCommand("UPDATE login SET [password] = '" + textBox3.Text + "' WHERE username = '" + textBox2.Text + "'", con);
com.ExecuteNonQuery();
MessageBox.Show("password successfully changed", "success!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
errorProvider1.SetError(textBox3, "passwords dont match");
errorProvider1.SetError(textBox4, "passwords dont match");
}
}
else
{
errorProvider1.SetError(textBox1, "wrong username");
errorProvider1.SetError(textBox2, "wrong pasword");
}
}
}
there is an error in the line if (dt.Rows[0][0].ToString() == "1") where it states that no data was found at that position, yet there are 5 rows in the data table.
when the code is run without the above line, as in //if (dt.Rows[0][0].ToString() == "1")
the code runs but no data is being updated in the table.
updated code again and still recived the same error:
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM login WHERE username= '" + textBox1.Text + "' AND [password]='" + textBox2.Text + "' ", con);
DataTable dt = new DataTable();
da.Fill(dt);
con.Open();
errorProvider1.Clear();
if (dt.Rows[0][0].ToString() == "1")
Try filling your DataTable as following -
string cmdString = "SELECT * FROM login WHERE username= '" + textBox1.Text + "' AND [password]='" + textBox2.Text + "' ";
OleDbCommand cmd = new OleDbCommand(cmdString,con);
con.Open();
var dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
con.Close()
Now you should get your data in table, provided that your select query is correct. Make sure you use using blocks on connection and command objects to dispose these when they are out of scope.
you are just declaring data table,not assigning any data
DataTable dt = new DataTable();
thats why when you try to get dt.Rows[0][0].ToString() it gives error
As you can try this:
OleDbDataAdapter custDA = new OleDbDataAdapter();
DataSet custDS = new DataSet();
DataTable custTable = new DataTable("Customers");
custTable.Columns.Add("CustomerID", typeof(String));
custTable.Columns.Add("CompanyName", typeof(String));
custDS.Tables.Add(custTable);
//Use ADO objects from ADO library (msado15.dll) imported
// as.NET library ADODB.dll using TlbImp.exe
ADODB.Connection adoConn = new ADODB.Connection();
ADODB.Recordset adoRS = new ADODB.Recordset();
adoConn.Open("Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI;", "", "", -1);
adoRS.Open("SELECT CustomerID, CompanyName FROM Customers", adoConn, ADODB.CursorTypeEnum.adOpenForwardOnly, ADODB.LockTypeEnum.adLockReadOnly, 1);
custDA.Fill(custTable, adoRS);
adoRS.Close();
adoConn.Close();
You can follow this reference
As noted by another, you never assign a value to the data table, that is why it is choking. Your query itself, by string concatenation will open you to SQL-Injection. Parameterize it. Finally, for your query, I would query all records for a given user ID, but get the user and password values based on only qualifying the user ID, not the password. This way, if you have more than 1 row returned, it will indicate duplicate user accounts and should get special attention. If it returns NO rows, then no such user. If it returns ONE row, then you can compare to the password entered and if matched, you have your correct user ID to run with.
starting with your
using( OleDbConnection con = ...)
{
// create command first.. Parameterize it. In this case "#" is parameter indicator
// for Access. parmUserName is the parameter name to be applied. I explicitly added
// "parm" in front to ensure differentiation between the parameter and actual column.
var cmd = new OleDbCommand(
#"select password from login where username = #parmUserName", con);
// Now, add the parameter of proper data type. The name of the parameter and it's value
cmd.Parameters.AddWithValue("parmUserName", textBox1.Text);
// create your data adapter now based on the command above
var da = new OleDbDataAdapter(cmd);
// NOW, create your data table object and have data adapter query and fill with rows.
var dt = new DataTable();
da.Fill(dt);
// NOW, check results.
if (dt.Rows.Count == 0)
MessageBox.Show("No such user account");
else if( dt.Rows.Count > 1)
MessageBox.Show("Duplicate user account");
else
{
// valid single record. Do the passwords match?
if (textBox3.Text.Equals(dt.Rows[0]["password"].ToString()))
{
MessageBox.Show("Valid login, allow to continue");
// Now, since it appears you are trying to UPDATE the password for the user,
// build new UPDATE command and parameterize it in a similar fashion
var cmdUpd = new OleDbCommand(
#"update login set password = #parmNewPwd where username = #parmUserName", con);
// Now, add the parameter of proper data type. The name of the parameter and it's value
cmd.Parameters.AddWithValue("parmNewPwd", textBox3.Text);
cmd.Parameters.AddWithValue("parmUserName", textBox1.Text);
if (cmd.ExecuteNonQuery() == 1)
MessageBox.Show("Password updated");
else
MessageBox.Show("Failed updating password");
}
else
MessageBox.Show("Invalid password");
}
}
FINAL NOTE. You should also look into cleaning data especially before building SQL commands. Never concatenate strings where users can manually enter data for SQL-Injection, parameterize them.
I keep getting this run time error, syntax error in from clause. I tried already using my sql query in access and it seems ok.
Here's my code and I am using C# windows form with text box and button
OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Misry27\Documents\Visual Studio 2010\Projects\Inventory\Inventory\bin\Debug\Inventory.mdb");
OleDbCommand cmd = new OleDbCommand("select * from Employee where username = '" + this.tbUsername.Text + "' and password = '" + this.tbPassword.Text + "';", conn);
OleDbDataReader dr;
conn.Open();
dr = cmd.ExecuteReader();
int count = 0;
while (dr.Read())
{
count = count + 1;
}
if (count == 1)
{
MessageBox.Show("Username or Password is correct");
}
else
{
MessageBox.Show("Username or Password Incorrect");
}
conn.Close();
As explained in the comments above, PASSWORD is a reserved keyword and need to be enclosed in square brackets when used in query executed from net.
The usual advice follows. Use parameterized query to avoid parsing problem and sql injections, use the using statement around your disposable objects.
using(OleDbConnection conn = new OleDbConnection(a correct connection string here))
using(OleDbCommand cmd = new OleDbCommand(#"select * from Employee
where username = ? AND [Password] = ?", conn);
{
conn.Open();
cmd.Parameters.AddWithValue("#p1", this.tbUsername.Text);
cmd.Parameters.AddWithValue("#p2", this.tbPassword.Text);
using(OleDbDataReader dr = cmd.ExecuteReader())
{
.....
}
}
access layer:
public bool AddStudent(string busStudentFullName, string busStudentFatherName)
{
con = new SqlCeConnection();
con.ConnectionString = "data source = C:\\Users\\hasni\\Documents\\Visual Studio 2010\\Projects\\UniversityManagementSystem\\UniversityManagementSystem\\UniversityDB.sdf";
con.Open();
ds1 = new DataSet();
//DataTable t = new DataTable();
// string sql = "SELECT * from AdminPassword where Admin Name ='" + AdminNameLogintextBox.Text + "' and Password='" + PasswordLogintextBox.Text + "'";
//string qry = "SELECT * FROM Students";
// string sql = "SELECT * from AdminPassword where Admin Name ='" + AdminNameLogintextBox.Text + "' and Password='" + PasswordLogintextBox.Text + "'";
string sql = "SELECT * FROM Students";
da = new SqlCeDataAdapter(sql, con);
//da = new SqlCeDataAdapter();
//DataTable t = new DataTable();
//da.Fill(t);
da.Fill(ds1, "Students");
//string userNameDB = Convert.ToString(ds1.Tables[0]);
// return userNameDB;
con.Close();
// string busStudentFullName;
//string busStudentFatherName;
string sql2 = "INSERT INTO Students (Student Full Name,Student Father Name) Values('"+ busStudentFullName + "','" + busStudentFatherName + "')";
da = new SqlCeDataAdapter(sql2, con);
da.Fill(ds1, "Students");
con.Close();
return true;
}
Business layer:
public bool getResponseForAddStudent(string studentName, string studentfathername)
{
bool var = access.AddStudent(studentName, studentfathername);
return var;
}
Presentation layer:
private void AddStudentButton_Click(object sender, EventArgs e)
{
string studentName = StudentNameBox.Text;
string studentfathername = StdFatherNameBox.Text;
bool var = _busGeneral.getResponseForLogin(studentName, studentfathername);
if (var)
{
MessageBox.Show("Student Added");
}
else
{
MessageBox.Show("Sorry");
}
}
Your Sql isn't valid, when columns have spaces in their name need to surround with square brackets: INSERT INTO Students (Student Full Name,Student Father Name)
instead needs to be
INSERT INTO Students ([Student Full Name],[Student Father Name])
If I understand what you are attempting to do, there are a number of issues with your code in addition to the brackets problem.
Firstly, you are closing the connection before performing the last DataAdapter.Fill operation.
And since you want to insert a record before (re)filling the DataAdapter with student data, you must first issue a ExecuteNonQuery statement using a SqlCeCommand object. Also, to avoid injection attacks and other problems you should ALWAYS use parameterized queries. I would also advise wrapping the code with try...catch to handle errors.
Here is what I think you are trying to achieve with the insert operation (I have only desk-checked the syntax):
// con.Close();
// string busStudentFullName;
SqlCeCommand cmd = db.CreateCommand();
cmd.CommandText = "INSERT INTO Students ([Student Full Name],[Student Father Name]) Values(#FullName, #DadsName)";
cmd.AddParameter("#FullName", busStudentFullName);
cmd.AddParameter("#DadsName", busStudentFatherName);
cmd.ExecuteNonQuery();
At this point you can fill the DataAdapter with student rows including the newly inserted one.
This is my code to display/search a record in a database table. How do I put a validation whether the roecord exists or not? It is searching through the ID of a member. how should I show a message if the record does not exist?
string connectionstring = "Server=Momal-PC\\MOMAL;Database=Project;Trusted_Connection=True;";
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionstring;
conn.Open();
SqlDataAdapter sda = new SqlDataAdapter("Select * from Members where Number = '" + SearchID.Text + "'", conn);
DataTable dtStock = new DataTable();
sda.Fill(dtStock);
dataGridView1.DataSource = dtStock;
conn.Close();
if( 0 == dtStock.Rows.Count ) // does not exist
You can use like this:
If(dtStock.Rows.Count > 0) // If dtStock.Rows.Count == 0 then there is no rows exists.
{
// Your Logic
}
See Here & Here. How to use Dataset and DataTables.
You can use DataRowCollection.Count property.
Gets the total number of DataRow objects in this collection.
If(0 == dtStock.Rows.Count)
Console.WriteLine("There are no rows in that datatable")
You can do something like this
If(dtStock.Rows.Count > 0)
{
//code goes here
dataGridView1.DataSource = dtStock;
}
else
{
//Record not exists
}
This SQL will be likely be much faster, as it will only return 0 or 1 rows to the client, rather than every matching row and every single column. Get out of the habit of using *
SELECT 1 As X WHERE EXISTS (
Select 1 from Members where Number = '" + SearchID.Text + "')"
public static int RowCount()
{
string sqlConnectionString = #" Your connection string";
SqlConnection con = new SqlConnection(sqlConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) AS Expr1 FROM Tablename", con);
int result = ((int)cmd.ExecuteScalar());
con.Close();
return result;
}