I have the following scenario: a program I made has three type of user accounts: superuser, administrator and consultant.
The login forms works well and through a method I can get the type of the user and open the respective main form of said user.
The problem is this: there are some forms that the users share. But, I don't know how to have the application know which of the three main forms it must return depending of the user.
Question is: there is a way for keep the value (user type) from the login form and use it on the other forms?
Here is how I get the value of type in the database:
public string sacartipo()
{string tipo = "";
username = usuario.Text;
obj.Usuario = usuario.Text;
password = contra.Text;
obj.Contrasena = contra.Text;
tipo = obj.Logeo(username, password);
return tipo; //This is the variable that stores the type of user.
}
Make every form's constructor accept the user type, so that whenever you show a new form you tell it which user will use it.
You can store the user type(after the user logs in) in a session variable like Session["role"]=value and use it anywhere you want.
You can store users in an enum
public enum Users { Superuser, Administrator, Consultant }
and have a static object of Users type in your application that is seen everywhere (global)
public Users User;
on Login assign the appropriate value to the User static object, for eg.
MyApplication.User = Users.Consultant;
and in each form check user's permission on Load, eg.
var adminPageAllowedUsers = new[] {Users.SuperUser, Users.Administrator};
if(admingPageAllowedUsers.Contains(MyApplication.User))
{
//do the rest
}
else
{
//redirect user to another form
}
this is the logic I wanted to give you, and the codes are not tested, so excuse me for possible errors.
Assume sacartipo() was a method of Form1 and you want to call it an get the return value, you add the following method in Form2:
string GetTipo() {
var currentContext=SynchronizationContext.Current;
var tipoLocal=default(string);
SendOrPostCallback d=
dummy => {
using(var x=new Form1())
tipoLocal=x.sacartipo();
};
if(null!=currentContext)
currentContext.Send(d, null);
else
d(null);
return tipoLocal;
}
In the code of Form2, you call GetTipo() and what you expect to do have been done.
Related
I'm trying to hide the parameters from the querystrings in my web application.
I have been able to do that by using the session to store temporary variables. So it would work like this:
1. Click the view profile button:
href="#Url.Action("RedirectWithId", "Redirect", new { act = "ProfileView", ctrl = "User", id = member.Id})"
2. Calls the redirection method and stores the temp data:
public class RedirectController : Controller
{
public ActionResult RedirectWithId(string act, string ctrl, int id)
{
Session["temp_data"] = id;
return RedirectToAction(act, ctrl);
}
}
3. Use it in the action method without the parameter:
public ActionResult ProfileView()
{
if (Session["temp_data"] == null)
{
return Redirect(Request.UrlReferrer.ToString());
}
int id = (int)Session["temp_data"];
var model = GetUserById(id);
return View(model);
}
So it works just fine, however, this way to hide parameters doesn't handle the case where let's say I go to a first profile(id 4), and then go to a second one(id 8). If from the second profile I press the back button on the navigator trying to go back to the first profile(id 4), I'm going to be redirected to the current profile(id 8), since 8 is the current value of the Session["temp_data"].
Is there a way to handle this perticular case? Or is the another totally different and better way to hide parameters in the URL?
Thank you!
You can try this instead of Session
TempData["temp_data"]
I came to the conclusion that since I am already using authorizations and roles within my application, I don't need to always hide the parameters. I can simply hide whenever I am passing a complex object as a parameter.
Due to a problem caused by having multiple forms on a single page, I used an AJAX call to a WebMethod to submit my form instead of using ASP controls. However, in doing this, the previous method I had used to create a new entry into my database no longer works because a WebMethod must be static.
I have authenticated my user already using ASPX authentication, and am trying to retrieve the username and ID of that user with codebehind. The user has already been authenticated on Page_Load, but it seems I cannot access this information through my WebMethod. Is this possible to do inside of a static WebMethod? Thank you for all of your help in advance!
[WebMethod]
public static void CreateJob()
{
Submit_Job();
}
public static void Submit_Job()
{
if (Page.User.Identity.IsAuthenticated)
{
try
{
string username = Context.User.Identity.Name;
}
catch
{
Context.GetOwinContext().Authentication.SignOut();
}
}
var manager = new UserManager();
var usernameDatabase = new ApplicationUser() { UserName = username };
usernameDatabase = manager.Find(username, "password here");
if (usernameDatabase != null)
{
IdentityHelper.SignIn(manager, usernameDatabase, isPersistent: false);
string jobTitle = Request.Form["jobTitle"];
using (var ctx = new CreateUserContext(ConfigurationManager.ConnectionStrings["myconnectionstring"].ConnectionString))
{
Job job = new Job()
{
job_title = jobTitle
};
ctx.Jobs.Add(job);
ctx.SaveChanges();
}
}
}
Edit:
There are errors for example with Page.User.Identity.IsAuthenticated -- Page, Context, and Request all appear that they cannot be static.
The specific error:
(An object reference is required for the non-static field, method, or property 'Control.Page') as well as with Context and Request.
Moving it from a simple comment
I had the same issue recently.
Luckily, whenever a user signs in our application, we store the user information encrypted into a session variable, so I retrieve that information, pass it to our user's class constructor, which decrypts it and I can use my logged in users info without a hassle.
So, my solution is to store the users info in the Session, but be careful what you store. Maybe serialize the users object and store in the session, then, whenever you need it
public void Page_Load()
{
// Retrieve authenticated user information
UserClass userObject = GetUserCredentials();
// Call a method that turns the authenticated user object into a string that contains the users session information. Given the sensivity of this information, might want to try to encrypt it or offuscate it. Store it in a session variable as a string
Session["UserContext"] = userObject.SerializeUser()
/* rest of the page code goes here */
}
[WebMethod(EnableSession=true)]
public static void CreateJob()
{
Submit_Job();
}
public static void Submit_Job()
{
// Lets get the authenticated user information through the session variable. Due to the static nature of the method, we can't access the Session variables directly, so we call it using the current HttpContext
string serializedUserInfo = )HttpContext.Current.Session["UserContext"].ToString();
// Let's create the users object. In my case, we have a overcharged constructor that receives the users serialized/encrypted information, descrypts it, deserializes it, and return a instance of the class with the deserialized information
UserClass userObject = new UserClass(serializedUserInfo);
// Do whatever the method has to do now!
}
On the subject of serialization, a quick google search with "c# object serialization" will bring you several good matches. XML and JSON are 2 of the most used kind of serialization, specially on web methods. Binary serialization is a good option to also obfuscate information of the logged in user
I need two global variables to be accessed by multiple winforms at various stages.
The first is in regards to a distinct user, after logging in to the app,
other winforms need to get data from sql server tables based on the user who logged in.
SqlCommand cmd = new SqlCommand("SELECT * FROM regClient WHERE client_ID = **[GLOBAL VARIABLE]**", con);
The second follows this in that the user can log in as either a Client or Student. Different statements need to be called based on this. This value is set by radiobutton on the login window.
So if radClient is checked set global to 'client', if radStudent is checked set global to 'student'
then with other winforms can call select statements or enable/visible based on what the global is.
I believe I can store variables in Programs.cs but I'm not sure.
Create a User class:
public class User
{
public enum eStatus
{
Client,
Student
}
public static eStatus Status { get; set; }
public static string Name { get; set; }
}
You didn't say what the one variable is, so I guessed it was some kind of identifier like their name.
You can set the User's status with:
User.Status = User.eStatus.Client;
and the name with:
User.Name = "Charlie";
You can access and set the values from anywhere.
Comment response:
The if would look like:
if (Program.User.Status == Program.User.eStatus.Client)
{
// commands
}
else // if (Program.User.Status == Program.User.eStatus.Student)
{
// commands
}
You don't need the second if since there are only two values User.Status can have.
I wrote the following code to log in to my application using C# and LINQ. It connected to a SQL service oriented database that I have created in Visual Studio. The problem that I am having is one that I do not understand and am hoping that someone can help me about here. I have created two message boxed to try to see the output of my code buy I am not getting anything from it.
If anyone could help that would be great!
public bool UserLogin(string User, string Pass)
{
var Database = new ExampleDataSet();
var query = from Employee in Database.Employee
where (Employee.EmployeeID.ToString() == Employee.ToLower() && Employee.Password == Pass)
select Employee;
if (query.Count() != 0)
{
return true;
MessageBox.Show("You are logged in");
}
return false;
MessageBox.Show("You are not logged in");
}
private void cmdLogin_Click(object sender, EventArgs e)
{
string User = (txtUser.Text);
string Pass = (txtPass.Text);
UserLogin(User, Pass);
}
From the code you wrote, it seems that the problem is that you compare the string representation of an Employee with its EmployeeId property Employee.EmployeeID.ToString() == Employee.ToLower(). This line will always return false unless you override ToString() method of Employee class to return the property EmployeeId (which I presume you didn't).
Try this instead (assuming that parameter User contains the name of the user):
using(var dataSet = new ExampleDataSet())
{
var loggedIn = dataSet.Employee.Any(e=>e.UserName == User && e.Password == Pass);
var message = loggedIn ? "You are logged in" : "You are not logged in";
MessageBox.Show(message);
return loggedIn;
}
When you return, the function execution will stop, because it's done and will return the value to what it was called from. So anything after your return won't happen. Try putting MessageBox.Show before return:
MessageBox.Show("You are logged in");
return true;
And the same for the false version.
The Message boxes wont show as they are after the return statements - move your message boxes to before the returns to see them.
I have made changes in your code....Your if-else part is not valid......You are comparign employee.ID with employee itself..Try out with following code.....
public bool UserLogin(string User, string Pass)
{
var Database = new ExampleDataSet();
var query = from Employee in Database.Employee
where (Employee.EmployeeID.ToString().ToLower().Equals(User.ToLower())&& Employee.Password.ToString().ToLower().Equals(Pass.ToLower())
select Employee;
if (query.Count() != 0)
{
MessageBox.Show("You are logged in");
return true;
}
else
{
MessageBox.Show("You are not logged in");
return false;
}
}
private void cmdLogin_Click(object sender, EventArgs e)
{
string User = (txtUser.Text);
string Pass = (txtPass.Text);
UserLogin(User, Pass);
}
If you mean user = employeeId
Employee.EmployeeID.ToString() == user.ToLower()
if not :
Employee.EmployeeName.ToLower() == user.ToLower()
About the message box, you should know any statement after return will not be executed
Writing your own user authentication is not recommended. It is very difficult to do it right, and in most cases you can use one that is already provided by Windows or the dot net framework.
For example, your application should not store the users passwords in plain text. If your application or database is compromised, the attacker will not only gain full access to your application, but a list of passwords which it is likely the users have also used elsewhere.
If you need to store the users credentials, they should first be salted, and then hashed with a secure hashing algorithm. This prevents anyone who gains access to the database from learning users passwords.
To verify the password, you look up the salt in the database, append the password to it, hash the result, and then compare that with the stored value. If they are the same, then the user entered the correct password.
If you are writing an application that will be used in a windows domain, you can use Active Directory groups to control access to your application. On the simplest level, you can store your application in a folder which is only accessible by the authorised users.
You can also use groups to control access to the database the application connects to. If you are using SQL server, each group should be placed in a SQL database role, which is in turn granted the necessary permissions for that role.
From within the application, you can look up the users group membership, and use it to determine which forms / menu options to show, or exit the application if they are not authorised.
If you are writing an ASP.Net application, consider using MemberShip and Roles which are built in to the framework.
Hi can I'm very new to windows forms. Here I want to maintain state (like session in web applications) in windows forms.
Actually i want to store user login details in session. But i think there is no concept of session in winforms. So what is the alternative method to handle this type of situation.
Regards,
Nagu
There is no concept of Session variables in windows forms. What you can do is:
Create a internal class that holds the User name and password and any other variables and enumerations needed across the application (Something like Common.cs). These can be accessed through public properties across the application.
Have a parameterized constructor for all the forms and send the user name and the password whenever you are showing the form.
public class MyForm : Form
{
private string userName;
private string password;
}
Since windows forms are statefull (opposed to stateless for web forms), you can just use a field in your Form class.
You need to think more in terms of scope than session; as long as an object remains in scope you will be able to pull values from its public properties/fields.
In your case it would make sense to store the user details in a static class:
public static class LoginInfo
{
public static string UserID;
}
Now you can access the UserID simply from anywhere in your code:
MessageBox.Show(LogInfo.UserID);
In winforms you can use variables that are exposed to other forms through methods or properties.
You can also use static variables.
In the following example, you would have a controller for each window or group of windows. The controllers would be passed to one another depending on how they need to collaborate (what knowledge they need to share, etc). The important thing is to keep your application state in the controllers and limit the windows to handling user input and events.
// pseudocode, because I do not know WinForms that much
class MainController
{
private Guid securityToken;
public Guid SecurityToken
{
get { return securityToken; }
set { securityToken = value; }
}
}
class LoginWindowController
{
MainController mainController;
LoginWindow loginWindow;
public LoginWindowController(MainController mainController)
{
this.loginWindow = new LoginWindow(this);
this.mainController = mainController;
}
public void Show()
{
loginWindow.IsVisible = true;
}
public void HandleLogin()
{
Guid token =
myobject.Authenticate(loginWindow.Username, loginWindow.Password);
if (token != Guid.Empty)
{
mainController.SecurityToken = token;
}
}
}
In reply to your comment to my first reply:
You are creating the new instance of the Login form. How is that supposed to have values. It is a Login form and hence I believe you will be closing it as the user enters user name and password and clicks OK or whatever.
Then, there is no way you can get the values from the Login form as it is closed. If you need to stick to this approach, this could be a way:
Do not close the Login form, just hide it.
Pass the current instance to the next form. Like this:
In Login form:
NextForm nxt = new NextForm(this);
The constructor of NextForm will look like:
public NextForm(LoginForm frm){
// Code here
}
Now in NextForm, you can access the properties through "frm".
from a program i was using with a login form to store global variables and to store the password as a secure string. Within the program I am able to "run as" a specific user when I call processes. You can use it for other things besides process.start.
//to run process as another user
//create these global variables on the first
//form or piece of code in your program
class usernameGlobalVariable
{
public static string var = "";
}
class passwordGlobalVariable
{
public static SecureString var;
}
// use these as event handlers for text fields
//for your login form
private void usernameTextBox_TextChanged(object sender, EventArgs e)
{
usernameGlobalVariable.var = usernameTextBox.Text;
}
private void passwordTextBox_TextChanged(object sender, EventArgs e)
{
SecureString passWord = new SecureString();
foreach (char c in passwordTextBox.Text.ToCharArray())
{
passWord.AppendChar(c);
}
passwordGlobalVariable.var = passWord;
}
//put this on form that launches program
//this assigns variables for process.start
//change fileName to path and name of program
// use \\ in paths
string fileName = "c:\\hdatools\\Ping2.exe";
string arguments = "";
string domain = "domain";
//start the process
//put this on the page along w the above variables that
//launches the app as another user
//the .var variables are global
{
Process.Start(
fileName,
arguments,
usernameGlobalVariable.var,
passwordGlobalVariable.var,
domain);
}
It's unclear to me whether you are talking about a web application or a stand along application based upon one of your responses. If you are talking about a web application, you can use the Session properties on the Page object.
It would set the variables like this:
Session["username"] = "Username";
Session["fullname"] = "User's full name";
You could then access like:
lblGreetings.Text = "Hi " + Session["fullname"];
Is that what you were after?