Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 603
ezechiele2517 Avatar asked Aug 06 '13 16:08

ezechiele2517


2 Answers

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)

like image 50
Nondeterministic narwhal Avatar answered Nov 12 '22 18:11

Nondeterministic narwhal


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

enter image description here

which has 2 inputs for Username and Password and a submit button entitled "Login"

enter image description here

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"] = "[email protected]";
            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
}
like image 3
Eduard Dumitru Avatar answered Nov 12 '22 17:11

Eduard Dumitru