4
votes

I am using custom Membership and Role providers inside the ASP.NET framework with Forms Authentication. These are working great. The Role provider is using a cookie to persist the roles, saving a trip to the database on each web request. I am also using the UserData string inside the FormsAuthenticationTicket to store the UserId.

I need to refactor my DAL out of the web project to its own project. The DAL has a dependency on retrieving the Current user’s ID as well as checking the roles for rights. How should my Authentication system change so I can use the Thread.CurrentPrincipal without referencing System.Web in the DAL project?

Currently the Provider Framework creates a RolePrincipal and FormsIdentity object and attaches it the the Thread.CurrentPrincipal.

I thought about creating a custom IPrincipal wrapper around the RolePrincipal during the Application_PostAuthenticateRequest event. In this event I can get the UserID from the FormsAuthenticalTicket and pass it to this new wrapperPrincipal along with the RolePrincipal.

Is this a valid approach? Will I end up causing some issues farther down in the project by messing with the Provider structure?

Thank you, Keith

protected void Application_PostAuthenticateRequest()
{
    if (Request.IsAuthenticated)
    {
        FormsIdentity identity = (FormsIdentity)User.Identity;

        if (identity != null)
        {
            FormsAuthenticationTicket ticket = identity.Ticket;

            int id = 1;

            if (identity != null)
            {
                int.TryParse(identity.Ticket.UserData, out id);
            }

            var wrapperPrincipal = new WrapperPrincipal(User, id);
            System.Threading.Thread.CurrentPrincipal = WrapperPrincipal;
        }
    }
}   



[Serializable]
public class WrapperPrincipal : IPrincipal
{        
    private IPrincipal principal;

    public WrapperPrincipal(IPrincipal principal, int userId)
    {
        this.principal = principal;
        this.Id = userId;
    }

    public int Id { get; set; }

    public IIdentity Identity
    {
        get { return principal.Identity; }
    }

    public bool IsInRole(string role)
    {
        return principal.IsInRole(role);
    }
}
1
I have the some doubt and I'm really interested in your question's outcome. Can you share your conclusion, if you've came to any?Arthur Nunes
Just extend your WrapperPrincipal with RolePrincipal instead of using IPrincipal and remove IPrincipal implementation methods and properties. The RolePrincipal implements IPrincipaluser357086

1 Answers

0
votes

i came across this question recently when i was trying to implement custom principal too. I did wrapper too and i think it is valid. It works perfectly with LukeP's approach in ASP.NET MVC - Set custom IIdentity or IPrincipal. You cant mess anything because it is just wrapper, u just delegete origin principal members, you dont even touch it. I would call it clever solution.