Storing/accessing user access roles C# Winforms - c#

I have designed several Client/Server applications. I am working on a project that involves a user logging in to gain access to the application. I am looking at the most efficient and "simple" method of storing the users permissions once logged in to the application which can be used throughout restricting access to certain tabs on the main form.
I have created a static class called "User" detailed below:
static class User
{
public static int _userID;
public static string _moduleName;
public static string _userName;
public static object[] UserData(object[] _dataRow)
{
_userID = (int)_dataRow[0];
_userName = (string)_dataRow[1];
_moduleName = (string)_dataRow[2];
return _moduleName;
}
}
When the user logs in and they have been authenticated, I wish to store the _moduleName objects in memory so I can control which tabs on the main form tab control they can access, for example; if the user has been assigned the following roles in the database: "Sales Ledger", "Purchase Ledger" they can only see the relevant tabs on the form, by way of using a Switch - Case block once the login form is hidden and the main form is instantiated. I can store the userID and userName variables in the main form once it loads by means of say for example:
Here we process the login data from the user:
DataAccess _dal = new DataAccess();
switch (_dal.ValidateLogin(txtUserName.Text, txtPassword.Text))
{
case DataAccess.ValidationCode.ConnectionFailed:
MessageBox.Show("Database Server Connection Failed!");
break;
case DataAccess.ValidationCode .LoginFailed:
MessageBox.Show("Login Failed!");
_dal.RecordLogin(out errMsg, txtUserName.Text, workstationID, false);
break;
case DataAccess.ValidationCode .LoginSucceeded:
frmMain frmMain = new frmMain();
_dal.GetUserPrivList(out errMsg,2); //< here I access my DB and get the user permissions based on the current login.
frmMain.Show();
this.Hide();
break;
default:
break;
}
private void frmMain_Load(object sender, EventArgs e)
{
int UserID = User._userID;
}
That works fine, however the _modules object contains mutiple permissions/roles depending on what has been set in the database, how can I store the multiple values and access them via a Switch-Case block?

If I am understanding properly, you want to be able to store permissions/roles as a value in a database per user.
I believe you can write an integer to a database field like : RolesID. Write to you database field the value of the flag. Something like:
[Flag]
public enum ROLES
{
Administrator = 1,
User = 2,
OtherRole3 = 4,
OtherRole4 = 8
}
You should be able to read that value in and assign to a field declared as:
ROLES userRoles = GetRoleValueFromDB();
I'm pretty certain I've done this before.
HTH...

Related

How to use variable static list when multi user access

this variable works fine if used by one user, but when used by two or more users then the "static" variable will be read by the next user, the first user instance when filling the gridview there are 5 rows of data and I try to access through other browser when entering the page, gridview on the second user already filled 5 rows of data in input by the first user. then how the solution to this problem? please see my code and give me an solutions. thanks.
static List<ServicesModels> _gridPackageDetail = new List<ServicesModels>();
private void AddListAction(string alfa, string beta)
{
ServicesModels data = new ServicesModels()
{
id_service_detail = Guid.NewGuid(),
scope_name = alfa,
detail_name= beta
};
_gridPackageDetail.Add(data);
}
public ActionResult GridPackageDetail()
{
ViewBag.DataListPackage = _gridPackageDetail.OrderBy(a => a.scope_name).ToList();
return PartialView();
}
my code in mvc3 controller.
The code is working fine, because this is what intended by "static", to have the same data for multi users. In your case you need to create a list or dictionary or multi-dimensional array (any data structure you are comfortABLE with) and save the data per use in it, and then retrieve the data when needed based on the user id.
static List<ServicesModels> _gridPackageDetail = new List<ServicesModels>();
private void AddListAction(string alfa, string beta)
{
ServicesModels data = new ServicesModels()
{
id_service_detail = Guid.NewGuid(),
scope_name = alfa,
detail_name= beta,
user_id = getTheID()// Get the id of the user
};
_gridPackageDetail.Add(data);
}
public ActionResult GridPackageDetail()
{
ViewBag.DataListPackage = _gridPackageDetail.OrderBy(a => a.scope_name && user_id ==getTheID()).ToList();
return PartialView();
}
replace getTheID() by your way of getting the id of the user.
This is used if you want to keep the data of all users. else you should remove the static keyword.

Setting unique Session variables at Application level

I have a Web Forms application that does not have a login page. Technically a user can access any page directly. However, I need to be able to identify who the logged-in user is on each page. I don't want to add code to each page. I would rather set a unique session variable at the start of the session. For this I added into my Global.asax.cs the following:
protected void Session_Start(object sender, EventArgs e)
{
if (Session["LoggedInUser"] == null)
{
string networkId = HttpContext.Current.User.Identity.Name;
using (UnitOfWork unit = new UnitOfWork())
{
if (networkId.IndexOf("HLM\\") > -1) { networkId = networkId.Substring(4, networkId.Length - 4); }
loggedInUser = unit.PersonRepository.GetByNetworkID(networkId);
Session["LoggedInUser"] = loggedInUser;
}
}
else
{
loggedInUser = (Person)Session["LoggedInUser"];
}
}
I now see that it sets the loggedInUser to whatever user last created a session. Meaning, if Mike goes to the site he will see data that represents him as the loggedInUser. However, if Kate goes to the site after him, Mike will now see Kate's data. Basically, the last one in overwrites everyone's settings and Session_Start is overwriting the value for loggedInUser for all active Sessions.
Based on this link: https://books.google.com/books?id=nQkyi4i0te0C&pg=PA202&lpg=PA202&dq=C%23+set+unique+session+variable+in+global.asax&source=bl&ots=GV9nlEUzE5&sig=E4TT3NDbjp1GwEehgU3pLXKdvr0&hl=en&sa=X&ved=0ahUKEwiU9f322tvSAhVF7yYKHYaXCtwQ6AEITzAI#v=onepage&q=C%23%20set%20unique%20session%20variable%20in%20global.asax&f=false
It reads that I should be able to set unique session variables for each new session but my results don't show that.
Am I misunderstanding how this works? I need to set a unique session value at the beginning of each session for each user.
I found the issue. The Session_Start is doing what is supposed to at a unique session level. The way I was referencing the session value was all wrong. Instead of accessing the session value I was actually doing:
Person loggedInUser = Global.loggedInUser;
Which makes sense that it was returning the latest user to start a session.

Add method - MVC - working with data entry into two tables

I have two classes:
**User
UseP where** User have its id (PK) and UserP has the id (FK) of User.
I'm working on MVC 4. Using Fluent API.
The classes are mapped within the project to connect to the database. My project is split into controllers, services, models and views.
I have a User screen that uses a UserPr field.
How can I instantiate it in class without being the way down? (that way does not work because of the relationship, otherwise work):
**CLASS USER.CS**
public string Login { get { return this.UserP.login } set { login = value }}
inclusion screen to add the User of items, I should also change the status of the screen, this status is within UserP.
Controller
public ViewResultBase Add(User model)
{
if (this.ModelState.IsValid)
{
try
{
this.Service.SaveUserP(model);
return this.SuccessView(true);
}
catch (ValidationException exception)
{
base.AddValidationErrors(exception);
return base.PartialView(model);
}
}
else
{
return base.PartialView(model);
}
}
Service
public void SaveUserP(User item)
{
//save fields from User (Running ok)
base.context.Usuario.Add(item);
//Attempt to save the login and their status in UserP
foreach (var userP in base.context.UserP.Where(x => x.IdUser == item.Id))
{
item.login = userP.Login;
userP.ParticipantType = 3;
base.context.UsersP.Add(userP);
}
}
I've tried that way, but I could not.
If the item.login is only working because login stand as [notmapped] in User.cs
To summarize: In the inclusion screen (User) I have a field that should bring (UserP) login.
When I trigger the method of inclusion, he should save the fields and save the User log in using UsuarioP IdUsuario as key and also changing the status of login (ParticipantType = 3)
The error I get:
Invalid column login (because really there is no login in User)
Time to debug it includes only the User fields, and even through the foreach.
I do not know how to operate, can help me? What if I have not been clear, I put more details
You will need to save the User input first before your foreach loop.
base.context.SaveChanges();

Where to store user data after login with WebForms

I'm developing a WebForms web application with VS2010 in C#. I use my custom login approach to authenticate users and I don't want to use Membership framework. After user login I want to store user data as userId, username, surname, email, etc., so I can access them during the user session in all pages.
How can I do that? I don't wanna store user data in the UserData property of the FormsAuthenticationTicket.
I found this approach: Should I store user data in session or use a custom profile provider?, but I don't understand how to implement it.
I have some question:
1)in my login page to authenticate user after check credentials on db I use : FormsAuthentication.SetAuthCookie(txtUserName.Value, true); now in my default page I have:
FormsAuthenticationTicket ticket = ((FormsIdentity)(User.Identity)).Ticket; and I use ticket.Name to show username. is it correct? why do you talk about thread using Thread.CurrentPrincipal.Identity.Name ?
2) I have this code in global.asax file to read user roles and store thems into HttpContext:
void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated) {
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnStr"].ConnectionString);
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT Gruppi.Name FROM Ruoli INNER JOIN Gruppi ON Ruoli.GroupID = Gruppi.GroupID INNER JOIN Utenti ON Ruoli.UserID = Utenti.UserID AND Utenti.Username=#UserName", conn);
cmd.Parameters.AddWithValue("#UserName", User.Identity.Name);
SqlDataReader reader = cmd.ExecuteReader();
ArrayList rolelist = new ArrayList();
while (reader.Read()){
rolelist.Add(reader["Name"]);
}
// roleList.Add(reader("Name"))
string[] roleListArray = (string[])rolelist.ToArray(typeof(string));
HttpContext.Current.User = new GenericPrincipal(User.Identity, roleListArray);
reader.Close();
conn.Close();
}
}
can I store user data into session as you wrote from my global.asax file rather then login.aspx page?
In the interest of easier debugging, I suggest using the Session Facade design pattern, described here, that will allow you to store the current user's data using the HttpContext.Current.Session object in a more organized fashion.
For instance, there would be a file (e.g., SessionFacade.cs) that is responsible for handling the values passed to/from the Session; in your case, it might look like:
public static class SessionFacade
{
public static int UserId
{
get {
if (HttpContext.Current.Session["UserId"] == null)
HttpContext.Current.Session["UserId"] = 0;
return (int)HttpContext.Current.Session["UserId"];
}
set {
HttpContext.Current.Session["UserId"] = value;
}
}
// ... and so on for your other variables
}
Then, somewhere else in your code, once you check that credentials are okay, you can do...
if (credentialsAreOk) {
SessionFacade.UserId = /* insert ID here */
// ...
}
...instead of manually assigning values to the Session object. This ensures your variables in Session are of the correct type, and will be easier to track while debugging. Then, to get the UserId from anywhere in your program, it's just SessionFacade.UserId.
(yes that snippet was from Eduard's answer; you should still look into that answer as it is informative as to how WebForms work; just keep in mind that calling the Session object manually in your code can be quite messy and that the Session Facade makes that process cleaner)
In case that by "web application by VS2010 in C#" you're talking about ASP.NET (MVC or Classic) and by "custom login approach" you're referring to FormsAuthentication then all you need to do is to store your later needed information at login time, onto the Session object.
Let's say you're using ASP.NET Classic and you have a login page
which has 2 inputs for Username and Password and a submit button entitled "Login"
In the button's (server side) OnClick event handler you should do something like this:
public partial class Login : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
}
private bool CheckUserPass(string username, string password) {
// access DB or some other form of storage service
return true;
}
protected void buttonLogin_Click(object sender, EventArgs e) {
bool credentialsAreOk = this.CheckUserPass(
this.textBoxUsername.Text,
this.textBoxPassword.Text
);
if (credentialsAreOk) {
this.Session["EMAIL_ADDRESS"] = "SomeEmail#SomeEmailProvider.com";
this.Session["OTHER_INFORMATION_KEY"] = "Some other stuff which you have access to during the login process";
this.Session["TIME_OF_LOGIN"] = DateTime.UtcNow;
FormsAuthentication.RedirectFromLoginPage(this.textBoxUsername.Text, createPersistentCookie: false);
}
}
}
So, in short, if you're using FormsAuthentication, then the username can be stored onto the session in the same way you're telling the FormsAuthentication system that current session should be transformed from non-authenticated to authenticated:
FormsAuthentication.RedirectFromLoginPage(this.textBoxUsername.Text, createPersistentCookie: false);
whereas other information can be placed on the Session object (just like you would add key value pairs to a Dictionary):
this.Session["TIME_OF_LOGIN"] = DateTime.UtcNow;
While it is obvious how you could later access that same information (for the respective user):
DateTime whenDidILogin = (DateTime) this.Session["TIME_OF_LOGIN"];
// this line of code can be used in any other page
// at any later time - it's like you have a global set of variables
// which exist for each and every distinct session you might have
it is maybe important to mention that the username (if not placed explicitly onto the Session object like the other examples) can be accessed by means of the Thread.CurrentPrincipal static property like so:
using System.Threading;
public void SomeWhereInYourApp() {
bool wasIAuthenticated = Thread.CurrentPrincipal.Identity.IsAuthenticated;
string whatIsMyUsername = Thread.CurrentPrincipal.Identity.Name;
// do something with that information
}
Membership provider helps you to store data and also for authentication purpose. Something like this:-
Session["UserName"] = Membership.GetUser().UserName

Generic collection in asp.net application state

I would like to store the logged in users in my asp.net application to a collection and store this collection in application state. I have a login Page and on Default.aspx page load event i have the following code:-
protected void Page_Load(object sender, EventArgs e)
{
users = (List<Users>)HttpContext.Current.Application["loggedUsers"];
if (User.Identity.IsAuthenticated == false)
{
Server.Transfer("Login.aspx");
}
if (User.Identity.Name != "")
{
users.Add(new Users { userName = User.Identity.Name.ToString() });
HttpContext.Current.Application["loggedUsers"] = users;
}
}
However when running the application, after the login an exception of Object reference not set to an instance of an object is being thrown on the code where i'm adding new objects to the list. If i comment the following line:
users = (List<Users>)HttpContext.Current.Application["loggedUsers"];
The application would run accordingly, howevever if let's say we have two users, USER A and USER B, and USER A logs in, he is added to list, however as soon as USER B logs it will overwrite USER A.
In my webservice i have the following method which will then return the list of currently logged users which works fine.
[WebMethod(EnableSession = true)]
public List<Users> getLoggedInUsername()
{
return (List<Users>)Application["loggedUsers"];
}
The problem is that when your first user is entering you have no value in the application with loggedUser key . It should be a common practice to check for NULL before casting it.
List<User> user = null;
if(HttpContext.Current.Application["loggedUsers"] == null)
{
user = new List<User>();
}
else
{
user = (List<User>)HttpContext.Current.Application["loggedUsers"];
}

Categories

Resources