Reputation: 55
I am working on an ASP.NET MVC application. I have implemented custom membership provider, principal and identity. In the custom provider I replace the HttpContext.Current.User in the ValidateUser() method as follows:
public sealed class CustomMembershipProvider : MembershipProvider { ... public override bool ValidateUser(string username, string password) { ... CustomIdentity identity = new CustomIdentity(...); CustomPrincipal cu = new CustomPrincipal(identity); HttpContext.Current.User = cu; ... } ... }
In the AccountController (calls the custom membership provider) I am able to access the custom identity as follows:
public class AccountController : BaseController { ... public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl) { ... CustomIdentity ci = (CustomIdentity)HttpContext.User.Identity; ... } ... }
All my controllers inherit the BaseController which calls a custom attribute as follows:
[CustomAttribute] public abstract class BaseController : Controller { ... }
I want my other controllers to access the custom identity within the custom attribute after it has been set by the AccountController as follows:
public class CustomAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); CustomIdentity ci = filterContext.HttpContext.User.Identity as CustomIdentity; ... } } }
What I have found is that filterContext.HttpContext.User is still set to GenericPrincipal and not my CustomPrincipal. So my custom identity is not accessible within my attribute filter. What do I have to do so that my CustomPrincipal is accessible within my attribute filter?
Thanks in advance.
Upvotes: 2
Views: 4133
Reputation: 3034
I don't know if this is "better" way, but it worked for me so far. I create a static UserContext
class that has CurrentUser
property. There I store the user entity I get from database and use it for user info data and authorization. I only use the HttpContext.Current.User
to check authentication.
Now the CurrentUser
property stores my user object in HttpContext
's Items
colletion (I have a wrapper around that so I can make it unit testable).
Upvotes: 0
Reputation: 55
After researching more about how application request events are fired (the specific order) and when context objects can be set I was able to set my custom principal and identity so that they are available to the filter (throughout the application for that matter).
I realized that the user must be authenticated before these entities could be set for use through the rest of the application. This, I found, could be done in the Application_AuthenticateRequest() method of global.asax.
So, I modified my logic as follows:
protected void Application_AuthenticateRequest(object sender, EventArgs e) { if (Request.IsAuthenticated) { // TODO: Add checks so we only do the following once per login. // Get the GenericPrincipal identity IIdentity ui = HttpContext.Current.User.Identity; /* Extract Name, isAuthenticated, AuthenticationType from the identity of the GenericPrincipal and add them including any custom properties to the custom identity. I added a few extra properties to my custom identity. */ CustomIdentity identity = new CustomIdentity(...); /* Although my custom principal does not currently have any additional properties, I created a new principal as I plan to add them in the future. */ CustomPrincipal principal = new CustomPrincipal(identity); // Set custom principal HttpContext.Current.User = principal; } }
This got me past my hurdle. Please guide me if there are other better ways to accomplish the same.
Thanks.
Upvotes: 2