I'v created a "Login" windows form app with WCF,
How to send the input username and password to WCF and check if the username in SQL?
private void loginbt_Click(object sender, EventArgs e)
{
string username = textBox1.Text;
string password = textBox2.Text;
//check username and password are not empty
if (username.Trim().Length != 0 && password.Trim().Length != 0)
{
checkPassword.CustomerServiceClient service= new checkPassword.CustomerServiceClient();
var enterPassword = service.checkPassword(username, password);
//check input value here with WCF?
}
}
I'm getting Index was outside the bounds of the array. exception when I add string getUsername = enterPassword[0].name;. It looks like the WCF did not get the input value from textbox, in other words checkPassword(null, null).
public Customer[] checkPassword(string name, string password){
List<Customer> customers = new List<Customer>();
SqlConnection connection = new SqlConnection(
"Data Source = 11111; Initial Catalog = 1111;" +
"User ID = 1111; Password = 11111");
connection.Open();
SqlCommand command = new SqlCommand("select customerId, customerName, address, password, phone from Customer where customerName='"+name+"'", connection);
SqlDataReader reader = command.ExecuteReader();
if (reader.Read()){
Customer newCustomer = new Customer(reader.GetString(1), reader.GetString(3));
string correctPW = reader.GetString(3);
if (correctPW == password)
{
customers.Add(newCustomer);
}
}
reader.Close();
connection.Close();
return customers.ToArray();
}
sorry, I am really confuse with this question, hope you can understand my question, thanks for help.
It is not possible that the service call got executed as checkPassword(null, null) because you call Trim on username and password further up in the execution sequence. You would have received a NullReferenceException before the service call if both variables were null.
One red flag that I see is that you are testing the trimmed (whitespace truncated) versions of username and password when deciding to make the service call, but yet you go ahead and used the unadulterated versions when passing them as parameters to the service call. Could it be that the service is not behaving the way you think it should because there is whitespace in the parameters?
What you really need to do is verify the values of username and password just prior to calling to the service. Ask yourself, "Does my service respond correctly using the parameter values specified?" The problem may be with the service and not the caller. You are going to have to do some old fashioned debugging here. That is something we cannot do for you so take off those socks and shoes and get your feet wet!
As a side note, it appears that you are passing a password in plain text across the network. It is not terribly difficult (actually it could be quite easy) for a middle man to intercept this information. And along the same lines I can see that you are open to SQL injection attacks as well. Knowing that you are using parameterless inline SQL I could tell you my username is x' or 'a'='a and that would cause all rows from the Customer table to be returned. I do not know if that would necessarily cause a security breach in your cases, but I hope you at least can imagine the kinds of havoc this could cause. I only mention all of this because your WCF appears to be security related.
Fixed my problem.
It is because I use the input username to select data from sql, so when I input a not exist username, it will give a error.
Thanks all.
Related
This question already has answers here:
ASP.NET Identity 2.0 check if current user is in role IsInRole
(4 answers)
Unable to configure AspNet.Identity using PostgreSQL
(2 answers)
Closed 4 years ago.
I have a little web application on asp.net MVC + PostgreSQL.
I have login page, where people enters their login/password. Right now I only have 1 user - admin. If login and pass are correct, I enter to mainForm.aspx page.
But I need to make a couple of users: user and director. When user logs in, he needs to be redirected to user.aspx page, when director logs in, he needs to be redirected to director.aspx page. All cases need to make login/pass check from PostgreSQL database.
How do I do that?
Here's my Login.aspx.cs code with only 1 user:
namespace User1.WebApp
{
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
}
protected void Button_Login_Click(object sender, EventArgs e)
{
var connString = "Host=localhost;Username=postgres;Password=123;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
string checkuser = "select count(*) from Login where name= '" + TextBoxUserName.Text + "' ";
NpgsqlCommand com = new NpgsqlCommand(checkuser, conn);
int temp = Convert.ToInt32(com.ExecuteScalar().ToString());
if (temp == 1)
{
string checkPasswordQuery = "select password from Login where name= '" + TextBoxUserName.Text + "'";
NpgsqlCommand passCom = new NpgsqlCommand(checkPasswordQuery, conn);
string password = passCom.ExecuteScalar().ToString().Replace(" ", "");
if (password == TextBoxPassword.Text)
{
Session["New"] = TextBoxUserName.Text;
Response.Redirect("MainForm.aspx");
}
else
{
Response.Write("Password is NOT correct !");
}
}
else
{
Response.Write("Username is NOT correct !");
}
}
}
}
}
You could do this just before
Response.Redirect("MainForm.aspx");
The way you can do it is to check the type of user and act accordingly.
Few comments regarding the current code:
Set the connection string in web.config and read it from there instead of having it hard coded in your code e.g. here.
The way you create your SQL statements makes your application vulnerable to SQL injection, one of the most common ways for someone to hack a site. Instead of doing this, prefer parameterized queries.
You make two round trips to the database, to check if the user exists and then to get her password. What about if you want to fetch one more information like the user type ? You would make one more round trip. You could eliminate all this to one round trip, provided that you can identify your users based on something unique like the username. Just fetch all the data for a specific username.
Let that someone can get access to the Login table of your database. How exposed are your application users ? 100%. All the passwords there are in clear text ! You should avoid this in any way. A naive solution is to hash the password and each time someone try to login to hash the password that the user provides and compare with the hash you have stored. A more professional approach of storing passwords is described at The right way to implement password hashing using PBKDF2 and C#. Look also for similar articles like the mentioned one. Security should be of paramount importance for your applications.
Are you able to store an extra field in the database to specify whether a login is Admin, User or Director?
You could use an Enum for this:
enum LoginRole
{
User = 0,
Director = 1,
Admin = 2
}
This Enum could be stored as an integer field in your Login table, called "role" or similar. You could then redirect to the appropriate page depending on this role.
I have updated your code with an example:
var connString = "Host=localhost;Username=postgres;Password=123;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
string checkuser = "select password, role from Login where name=#username";
using (var com = new NpgsqlCommand(checkuser, conn))
{
com.Parameters.AddWithValue("#username", TextBoxUserName.Text);
using (var reader = com.ExecuteReader())
{
if (reader.Read())
{
string password = reader["password"].ToString();
LoginRole role = (LoginRole)reader["role"];
if (password == TextBoxPassword.Text)
{
Session["New"] = TextBoxUserName.Text;
switch (role)
{
case LoginRole.User:
Response.Redirect("user.aspx");
break;
case LoginRole.Admin:
Response.Redirect("MainForm.aspx");
break;
case LoginRole.Director:
Response.Redirect("director.aspx");
break;
}
}
else
Response.Write("Password is NOT correct !");
}
else
Response.Write("Username is NOT correct !");
}
}
}
Please note, using parameters in your queries in this case would be preferred, as appending the string from the textbox straight into the SQL query is vulnerable to SQL injection.
You were also making two calls to the database per login - one to check the username and another to check the password. I have addressed this in my above sample to only make one call to the database.
I am just learning c# and sql server. This question has been asked a couple of times but the solutions posted don't seem to help me.
I have a table called "LoginInfo" that has a user's "email" and "pass".
In visual studio i have this method that checks a users login information
private boolean dbQueryLogin(string email, string password)
{
string com = "SELECT pass FROM LoginInfo WHERE email = XXXXX#yahoo.com";
SqlCommand command = new SqlCommand(com, conn);
SqlDataReader reader = command.ExecuteReader();
return reader.GetString(0).Equals(password);
}
This keeps on throwing the error "Additional information: The multi-part identifier "XXXX.edu" could not be bound."
The syntax looks right to me, is there anything i'm missing??
The clue is in the error message:
The multi-part identifier "XXXX.edu" could not be bound.
That strongly suggests that the problem isn't with identifying your table - it's with the bit that ends with "edu", which seems like to be an email address.
The immediate problem is that you've forgotten to quote a value. The deeper problem is that you should be using parameterized SQL anyway, to avoid SQL injection attacks, conversion problems and unreadable code. Given that the value you've given in the same code isn't the same as what's in the error message, I suspect you really have code like:
string sql = "SELECT pass FROM LoginInfo WHERE email = " + email;
Don't do that. Use parameterized SQL instead:
private boolean dbQueryLogin(string email, string password)
{
string sql = "SELECT pass FROM LoginInfo WHERE email = #email";
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(sql))
{
command.Parameters.Add("#email", SqlDbType.NVarChar).Value = email;
using (var reader = command.ExecuteReader())
{
// FIXME: What do you want to do if
// there are no matches?
reader.Read();
return reader.GetString(0) == password;
}
}
}
}
This still isn't good code though:
Don't store plain-text passwords in a database
Handle the case where there are no results
Don't build your own authentication system at all; use an existing one written by people with more experience in securing data
I am trying to create a login page where you would enter in a username and a password. It will query the database for the information you typed in, and if it is in the database, it will log me into the program. If not, it will display a message saying information is not correct.
Here is what I have so far.
private void okButton_Click(object sender, RoutedEventArgs e)
{
try
{
SqlConnection UGIcon = new SqlConnection();
UGIcon.ConnectionString = "XXXXXXXXX; Database=XXXXXXXX; User Id=XXXXXXX; password=XXXXXXXXX";
UGIcon.Open();
SqlCommand cmd = new SqlCommand("SELECT User(Username, '') AS Username, User(Password,'') AS Password, FROM User WHERE Username='"
+ txtUsername.Text + "' and Password='" + txtPassword.Password + "'", UGIcon);
SqlDataReader dr = cmd.ExecuteReader();
string userText = txtUsername.Text;
string passText = txtPassword.Password;
while (dr.Read())
{
if (this.userText(dr["stUsername"].ToString(), userText) &&
this.passText(dr["stPassword"].ToString(), passText))
{
MessageBox.Show("OK");
}
else
{
MessageBox.Show("Error");
}
}
dr.Close();
UGIcon.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
But, the only problem is it does not work at all. I am not sure I have the correct statements to query the database either. I am also getting an error on the "this.userText" As well.
{
if (this.userText(dr["stUsername"].ToString(), userText) &&
this.passText(dr["stPassword"].ToString(), passText))
{
For the error I'm getting, it tells me the WPF does not contain a definition for it
I am a little unsure of how to fix it and go about it as this is the first time I've had to do this. But I think I have a decent start to it though.
There are a couple of things wrong with this structure:
this.userText(dr["stUsername"].ToString(), userText)
First, userText isn't a function, it's a local variable. So I'm not sure what you're even trying to do by invoking it as a function. Are you just trying to compare the variable? Something like this?:
this.userText.Equals(dr["stUsername"].ToString())
Second, the error is telling you that the object doesn't contain a definition for userText because, well, it doesn't. When you do this:
this.userText
you're specifically looking for a class-level member called userText on the object itself. But your variable is local to the function:
string userText = txtUsername.Text;
So just drop the this reference:
userText.Equals(dr["stUsername"].ToString())
Third, the column reference is incorrect. Note how you define the columns in your SQL query:
SELECT User(Username, '') AS Username, User(Password,'') AS Password ...
The column is called Username, not stUsername:
userText.Equals(dr["Username"].ToString())
Edit: #Blam made a good point in a comment, which demonstrates a logical error in the code. If no results are returned from your query, the while loop will never execute. So no message will be shown. You can check for results with something like HasRows:
if (dr.HasRows)
MessageBox.Show("OK");
else
MessageBox.Show("Error");
This kind of renders the previous things moot, of course. But it's still good to know what the problems were and how to correct them, so I'll leave the answer whole for the sake of completeness regarding the overall question.
A few other notes which are important but not immediately related to your question...
Your code is vulnerable to SQL injection attacks. You'll want to look into using parameterized queries instead of concatenating string values like that. Essentially what this code does is treat user input as executable code on the database, allowing users to write their own code for your application.
Please don't store user passwords in plain text. The importance of this can not be overstated. The original text of a password should never be readable from storage. Instead, store a hash of the password. There's a lot more to read on the subject.
Look into using blocks to dispose of resources when you're done with them.
SqlCommand cmd = new SqlCommand("SELECT count(*) FROM User WHERE Username='"
+ txtUsername.Text + "' and Password='" + txtPassword.Password + "'", UGIcon);
Int32 rowsRet = (Int32)cmd.ExecuteScalar();
if(rowsRet > 0)
{
MessageBox.Show("OK");
}
else
{
MessageBox.Show("Error");
}
You still have exposure to SQL injection attack.
I am using ASP.NET membership because this is not typical website to have that kind of authentication. I have table that Admin assigns with Uname and Password (Encrypted).
I have a LogIn page when clicked on Login button I need to search for the user in my DB table.
public void getuserinfo()
{
String var = System.Configuration.ConfigurationManager
.ConnectionStrings["KKSTechConnectionString"].ConnectionString;
SqlConnection conn = new SqlConnection(var);
SqlCommand myCmd = new SqlCommand("SELECT Username, Pass FROM Users", conn);
conn.Open();
if(TextBox1== Username) && (TextBox2== Password) <- I am not able to get this right :(
{
//How do I get his info??
}
}
*Database table for dbo.users:*
Uname(PK) | Pass | EmpID (FK)
I want to first decrypt the password and then compare it with the TextBoxPassword..
Please help.
Another approach will be to hash the password entered at user screen and compare that with the hashed password stored at the database.
Now, use your function like this.
public void ValidateUser()
{
var connectionString = System.Configuration.ConfigurationManager
.ConnectionStrings["KKSTechConnectionString"].ConnectionString;
var userName = txtUserName.Text;
var hashedPassword = Helper.ComputeHash(txtPassword.Text, "SHA512", null);
// this query should be parameterised when used in production to avoid SQL injection attacks
var query = String.Format("SELECT Username, Pass FROM Users WHERE Username='{0}' AND Pass='{1}'",
userName,
hashedPassword);
using(var connection = new SqlConnection( connectionString ))
using(var command = new SqlCommand(query, connection ))
{
conn.Open();
SqlDataReader reader=command.ExecuteReader();
if(reader.Read())
{
}
reader.Close();
}
}
Few questions before we get to solution:
How are you sending username and password from client to server side? Is it plain text?
Where does encryption happens?
Have you written encryption code or using one of the standards available?
In your code, I can notice following issues:
You have created the connection object and command object although you have never executed the query on the database.
The query you are using return entire user table which is definitely not required. You already have the user inputs for username and password so just find if they are correct.
Make your query parameterized and send the input to database. There, check if the username and password match. If they do, send back user details (which you will need somewhere in the application, I suppose) or else either, throw exception or return null.
Make sure to take care of encryption/decryption before matching username and password.
I am trying to develop a simple user management system for the admin of the web application. I am using ASP.NET Wizard Control for this task.
I just put a TextBox for writing the username and when the admin clicks on the Next button, the system should check if the username existed in the database or not. If it is existed, the system should display his information in a placeholder for the admin.
I am struggling with this task. I did the following in the code-behind:
//For checking the user
if (Request.QueryString["Username"] != null)
{
String strUserName = Request.QueryString["Username"];
//Check userName Here
String strReturnStatus = "false";
if (CheckUsername(Request.QueryString["Username"]) == true)
{
strReturnStatus = "true";
}
Response.Clear();
Response.Write(strReturnStatus);
Response.End();
}
Now, I think to create a second method called CheckUsername which I don't know what I should put it inside it:
private bool CheckUsername(string p)
{
//throw new NotImplementedException();
}
It may seem that this question is simple or stupid, but I am a new developer and I could not be able to find a simple resource that could help me in this issue particularly.
I believe the following method is what you're after:
private bool CheckUsername(string username)
{
string connString = "";
string cmdText = "SELECT COUNT(*) FROM Users WHERE Username = #username";
using(SqlConnection conn = new SqlConnection(connString))
{
conn.Open(); // Open DB connection.
using(SqlCommand cmd = new SqlCommand(cmdText, conn))
{
cmd.Parameters.AddWithValue("#username", username)); // Add the SQL parameter.
int count = (int)cmd.ExecuteScalar();
// True (> 0) when the username exists, false (= 0) when the username does not exist.
return (count > 0);
}
}
}
You can fill in the blanks (e.g specify a connection string connString and modify cmdText). The SQL query I specified in cmdText is under the assumption of a typical user management system where you have common table names and columns; Users (table) and Username (column). It's hard to justify as you haven't specified the structure. Modify it to suit your applications needs.
The method of counting how many records exist is quite common in most cases. I frequently use that method of checking/validating things as I see fit.
Further information about the code (classes) I used in my example above:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.aspx
I also advise you read about data access (not that link). I'll leave you to that.
I adjust some point in your code:
if (!string.IsNullOrEmpty(Request.QueryString["Username"]))
{
---
---
if (CheckUsername(Request.QueryString["Username"]))
{
---
---
}
Refer to this link as tutorial for your task: http://www.codeproject.com/KB/database/sql_in_csharp.aspx