|
Hi forum members,
I am very new beginner in programming. I am trying to develop a window application form database project. The database has four different user roles that log in at the UserLogin form (i.e. Admin, Accountant, HR and ReadOnly).
When any of the users logs in, they are all redirected to a Dashboard with four link buttons named; Admin, Accountant, HR and ReadOnly; that open to the individual's access pages. Now, with the exception of the Admin, I want all the other roles buttons on the Dashboard disabled except the button of the role user who logged in.
I will appreciate if someone could assist me modify my code in order to achieve the expected success.
Below is a section of my login code:-
<pre> private void loginButton_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["con"].ConnectionString);
SqlCommand command = new SqlCommand();
con.Open();
string userText = userTextBox.Text;
string passText = pwdTextBox.Text;
SqlCommand cmd = new SqlCommand("select role from UsersLogin where UserName='" + userTextBox.Text + "'and Password='" + pwdTextBox.Text + "'", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
MessageBox.Show("Welcome to the Dashboard");
this.Hide();
dashboard.Show();
cmd = new SqlCommand("SELECT Role from UsersLogin where Username=@Username", con);
cmd.Parameters.AddWithValue("@Username", userText);
string role = cmd.ExecuteScalar().ToString();
MessageBox.Show("Welcome " + role);
con.Close();
}
else
{
MessageBox.Show("Access Denied!!");
Application.Exit();
}
con.Close();
}
modified 9-Nov-19 4:16am.
|
|
|
|
|
I know you are a student, but ... don't do it like that!
Never concatenate strings to build a SQL command. It leaves you wide open to accidental or deliberate SQL Injection attack which can destroy your entire database. Always use Parameterized queries instead.
When you concatenate strings, you cause problems because SQL receives commands like:
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood' The quote the user added terminates the string as far as SQL is concerned and you get problems. But it could be worse. If I come along and type this instead: "x';DROP TABLE MyTable;--" Then SQL receives a very different command:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable; Which SQL sees as three separate commands:
SELECT * FROM MyTable WHERE StreetAddress = 'x'; A perfectly valid SELECT
DROP TABLE MyTable; A perfectly valid "delete the table" command
And everything else is a comment.
So it does: selects any matching rows, deletes the table from the DB, and ignores anything else.
So ALWAYS use parameterized queries! Or be prepared to restore your DB from backup frequently. You do take backups regularly, don't you?
You know how to use them, so ignoring that for your login page is just plain stupid, as
1) Anyone can log in as any user without needing a password.
2) Anyone can delete your DB without even having a valid username!
To add to that, a cardinal sin: Storing passwords in plain text[^]
Never store passwords in clear text - it is a major security risk. There is some information on how to do it here: Password Storage: How to do it.[^]
And remember: if you have any European Union users then GDPR applies and that means you need to handle passwords as sensitive data and store them in a safe and secure manner. Text is neither of those and the fines can be .... um ... outstanding. In December 2018 a German company received a relatively low fine of €20,000 for just that.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Users do not need to know what other roles exist on the system, especially users with no special rights. When a user logs in you should find their role details in the database. From that information you can automatically take them to the page which is appropriate to their role; there is no need for the four buttons.
modified 9-Nov-19 5:33am.
|
|
|
|
|
Except if the User has multiple roles!
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
Except you code that in the DB as a bitfield to allow for multiple roles: role AND (HR OR Accountant) != 0
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
That is easy to manage by the use of permission flags; as is evident here on CodeProject.
|
|
|
|
|
I was trying to be cheeky, of course the static set of buttons is a lousy design, I generally use a combobox if the user has multiple roles.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
You need to completely isolate the log-in process from the display of any UI, using the guidelines for DB access, and password encryption, you've received on this thread.
Once you have a valid log-in, then run the app that shows the UI (using Process.Start, or some other technique).
You can create a Form as a template that will contain all the Controls shared by every role, and, then, create other, role-specific, Forms that inherit from the template.
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
We're drowning a beginner here Still, you are right; you explained the what, I'll add the why.
When you have a button on a WinForm, you can inspect its properties. So, if I see a disabled button, I'll simply toggle the "enabled" property to gain access. If there's no button visible, I'll look at the form and check if there's an invisible button as a child. That means hiding/disabling buttons is not secure.
Use the .NET Windows Forms Spy[^]
I dislike the idea of asking the user for a password in WinForms; if need be, all assemblies can be decompiled, adapted, and recompiled. For ASP that's less of an issue - but then I'd assume an AD that does the authentication, which means you don't need to provide yet another login.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Eddy Vluggen wrote: When you have a button on a WinForm, you can inspect its properties. So, if I see a disabled button, I'll simply toggle the "enabled" property to gain access. If there's no button visible, I'll look at the form and check if there's an invisible button as a child. That means hiding/disabling buttons is not secure. If you believe the OP is a "beginner," do you think they will understand this ?
Eddy Vluggen wrote: I dislike the idea of asking the user for a password in WinForms; if need be, all assemblies can be decompiled, adapted, and recompiled. For ASP that's less of an issue - but then I'd assume an AD that does the authentication, which means you don't need to provide yet another login. If the app stores no passwords, how can any form of hacking the app discover them ... for that matter, lots of Winform apps consume the plain-text user-entered password, hash it, salt it, and use that to query the DB for a check.
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
BillWoodruff wrote: If you believe the OP is a "beginner," do you think they will understand this ? No, but more people reading this thread then OP, no?
BillWoodruff wrote: If the app stores no passwords, how can any form of hacking the app discover them ... That's the point; if you leave the authentication to the AD, there's little risk.
BillWoodruff wrote: for that matter, lots of Winform apps consume the plain-text user-entered password, hash it, salt it, and use that to query the DB for a check. In which case you can decompile, and add a logging-statement for the unsalted variables, recompile.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Eddy Vluggen wrote: When you have a button on a WinForm, you can inspect its properties. I just tried that but could not find how to view or change the properties.
|
|
|
|
|
Can't find the app right now, but there's an application that lets you change values of properties of a running .NET application. It is similar to the WinSpy-app.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Not quite the same as "inspect the properties, and change them".
|
|
|
|
|
It was possible with that application, with the exception of readonly properties.
--edit
Similar to Accessibility tools - Inspect - Win32 apps | Microsoft Docs[^], which is already obsoleted. Buggy internet today, so Googling may take a bit
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
modified 10-Nov-19 13:41pm.
|
|
|
|
|
Eddy appears to be using a very expensive (UFT from MicroFocus, US $ 2~3k per seat) testing engine with some .NET add-in.
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
Nah, it was something free; but there's a boatload of links for the searchterms. I'll post a link in the lounge if I stumble on it.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Using .NET: Deliver The Power Of Spy++ To Windows Forms | Microsoft Docs[^]
MS wrote: When you select a control, the PropertyGrid shows properties on that control. You can examine or change property values here. You should note that custom types are supported as long as they are binary serializable (see Basic Serialization). It will fail with an exception when you run it. There's similar code on Github, which I haven't tried yet. If you want the link, drop me a message.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
I don't see how all this relates to this thread. The issue here is not what you can do by hacking, but how to securely isolate password login from the app that runs after successful login.
The link you posted was to the expensive MicroFocus tool
cheers, Bill
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
BillWoodruff wrote: he issue here is not what you can do by hacking, but how to securely Our ideas on security may vary; I do not see any login in .NET WinForms as being "secure".
BillWoodruff wrote: The link you posted was to the expensive MicroFocus tool The first, yes, because I could not find the tool imediatly. The second link points to MSDN which will fail on W10.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
I have the following C # statement:
...
using (SoundPlayer player = new SoundPlayer(Properties.Resources.ring))
{
player.Play();
while (If the bell is running, wait here)
{
if (player.Stop()==true)
{
this.progressBarControl1.Visible = false;
}
}
}
...
I want to check if the ringer is running or stopping, if it is running then wait until it stops before running this.progressBarControl1.Visible = false.
|
|
|
|
|
If you need to know when the sound has finished playing, you'll have to use the PlaySync method[^].
However, if you do that from the UI thread, your application will stop responding until the sound finishes. You'll probably want to play the sound on a background thread to avoid this problem. The simplest option would probably be to use a BackgroundWorker instance[^] - put the SoundPlayer code in the DoWork event handler, and the code to hide the progress bar in the RunWorkerCompleted event handler.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
use PlaySync() runs fine, but using backgroundWorker1 is difficult to use and the computer freezes
|
|
|
|
|
Member 2458467 wrote: backgroundWorker1 is difficult to use and the computer freezes
Then you're using it wrong.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I do not know how to use backgroundWorker in my code so the device crashes, I troubleshoot I see Debug.Print("Status: PLAY") and Debug.Print("Status: STOP") appear only once, You see my code, did I write anything wrong ?
bool _isStopped = true;
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
lblStatusPlaySound.ForeColor = Color.Violet;
lblStatusPlaySound.Text = "Status: PLAY/STOP";
}
private void btnPlaySound_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
using (SoundPlayer player = new SoundPlayer(Properties.Resources.ring))
{
player.Play();
}
while (_isStopped == true)
{
if (backgroundWorker1.IsBusy != true)
{ _isStopped = true; }
else
{ _isStopped = false; }
lblStatusPlaySound.ForeColor = Color.Green;
lblStatusPlaySound.Text = "Status: PLAY";
lblStatusPlaySound.Refresh();
Debug.Print("Status: PLAY");
}
lblStatusPlaySound.ForeColor = Color.Red;
lblStatusPlaySound.Text = "Status: STOP";
lblStatusPlaySound.Refresh();
Debug.Print("Status: STOP");
}
|
|
|
|
|