views:

30

answers:

1

I have an .aspx page that contains an <asp:Login> web control.

For authentication, I have another class (MyMembershipProvider) that inherits the System.Web.Security.MembershipProvider class.

The login process is working fine - i.e. username/password is properly authenticated by the MyMembershipProvider object.

My question is in regards to setting System.Web.SessionState.HttpSessionState.Session variables.

After a user has been successfully authenticated (by the MyMembershipProvider class), I would like to create custom Session vars for that user.

Initially, I thought I would be able to set the Session variables in the <asp:Login> control's LoggedIn event handler - something like this:

protected void LoginUser_LoggedIn(object sender, EventArgs e)
{
    //Get the UserName of the authenticated user
    string userName = Thread.CurrentPrincipal.Identity.Name;

    //Call the business layer to get more info on the authenticated user
    Entities.User user = BizLayer.GetUser(userName);

    //Set session vars for the authenticated user
    Session["LastName"] = user.LastName;
    Session["FirstName"] = user.FirstName;
    Session["Email"] = user.Email;
}

The problem that I am noticing is that when the LoggedIn event is fired the Thread.CurrentPrincipal.Identity.Name has not yet been set to the Username that was used when the user logged in. Therefore, the call to the BizLayer.GetUser() returns an empty User object which, of course, causes the Session setters to be useless.

My guess is that since I'm using a custom MembershipProvider, the <asp:Login> event handlers (LoggedIn, Authenticated, LoggingIn) are not working as I am expecting them to.

Is there another event handler that I should be using to set the Session variables? Or, can you point me in the right direction that would accomplish the same thing that I am describing?

Until I hear of a better way, I have implemented the following:

I changed the DestinationPageUrl attribute of the <asp:Login> control to point to a page that will do the job of setting the Session vars. Then, after I set the Session vars, I call Response.Redirect() to go the page that used to be set in the DestinationPageUrl attribute.

The pertinent code looks something like this:

Login.aspx web page has a Login control similar to...

<asp:Login ID="LoginUser" runat="server" DestinationPageUrl="SetSessionVars.aspx">

SetSessionVars.aspx web page has a method that sets the Session vars and redirects user to some page...

protected void Page_Load(object sender, EventArgs e)
{
    this.SetSessionVars();
    Response.Redirect("foo.aspx");
}

private void SetSessionVars()
{
    //Get the UserName of the authenticated user
    string userName = Thread.CurrentPrincipal.Identity.Name;

    //Call the business layer to get more info on the authenticated user
    Entities.User user = BizLayer.GetUser(userName);

    //Set session vars for the authenticated user
    Session["UserId"] = user.UserId;
    Session["LastName"] = user.LastName;
    Session["FirstName"] = user.FirstName;
    Session["Email"] = user.Email;
}
A: 

Why don't you just capture the username from the login form instead of getting it from Thread.CurrentPrincipal.Identity.Name?

The order of these things in ASP.NET is really not intuitive because the identity gets loaded before Page_Load and then doesn't get updated at that Logged_In event like you would expect.

Edit: since you don't like this, in your business layer you will want to add something like the below.

var genericIdentity = new System.Security.Principal.GenericIdentity(username);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(genericIdentity, roles);
jarrett