using custom IPrincipal and IIdentity in MVC3
Asked Answered
J

1

21

I create my own IPrincipal and IIdentity implementation as shown below:

[ComVisible(true)]
[Serializable]
public sealed class CustomIdentity : IIdentity {

    private readonly string _name;
    private readonly string _email;
    // and other stuffs

    public CustomIdentity(string name) {
        _name = name.Trim();
        if(string.IsNullOrWhiteSpace(name))
            return;
        _email = (connect to database and read email and other stuffs);
    }

    public string Name {
        get { return _name; }
    }

    public string Email {
        get { return _email; }
    }

    public string AuthenticationType {
        get { return "CustomIdentity"; }
    }

    public bool IsAuthenticated {
        get { return !string.IsNullOrWhiteSpace(_name); }
    }

}


[ComVisible(true)]
[Serializable]
public sealed class CustomPrincipal : IPrincipal {

    private readonly CustomIdentity _identity;

    public CustomPrincipal(CustomIdentity identity) {
        _identity = identity;
    }

    public bool IsInRole(string role) {
        return _identity != null && 
               _identity.IsAuthenticated &&
               !string.IsNullOrWhiteSpace(role) &&
               Roles.IsUserInRole(_identity.Name, role);
    }

    IIdentity IPrincipal.Identity {
        get { return _identity; }
    }

    public CustomIdentity Identity {
        get { return _identity; }
    }

}

Also, I create a HttpModule and in its AuthenticateRequest event, I do this:

    public void Init(HttpApplication context) {
        _application = context;
        _application.AuthenticateRequest += ApplicationAuthenticateRequest;
    }

    private void ApplicationAuthenticateRequest(object sender, EventArgs e) {
        var formsCookie = _application.Request.Cookies[FormsAuthentication.FormsCookieName];
        var identity = formsCookie != null
             ? new CustomIdentity(FormsAuthentication.Decrypt(formsCookie.Value).Name)
             : new CustomIdentity(string.Empty);
        var principal = new CustomPrincipal(identity);
        _application.Context.User = Thread.CurrentPrincipal = principal;
    }

Also, I create my own Controller and WebViewPage like these:

public abstract class CustomController : Controller {
    public new CustomPrincipal User {
        get {
            var user = System.Web.HttpContext.Current.User as CustomPrincipal;
            return user;
        }
    }
}


public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel> {
    public new CustomPrincipal User {
        get {
            // (Place number 1) here is the error I'm speaking about!!!
            var user = HttpContext.Current.User as CustomPrincipal;
            return user;
        }
    }
}

as shown in above code, it seems everything is right; But as you can see, in Place number 1 I can't access the CustomPrincipal! Means in this place, I have a RolePrincipal instead of having a CustomPrincipal. e.g. HttpContext.Current.User is a RolePrincipal instead of CustomPrincipal. But the RolePrincipal.Identity property is a CustomIdentity!

Jigaboo answered 24/5, 2012 at 17:17 Comment(0)
J
20

Your mistake is here:

_application.AuthenticateRequest += ApplicationAuthenticateRequest;

There is a HttpModule named RoleManagerModule that invokes a method in HttpApplication.PostAuthenticateRequest and sets the HttpContext.Current.User to RolePrincipal. So, you were setting the User in AuthenticateRequest and the RoleManagerModule sets it in PostAuthenticateRequest, means after your set, so overrides your settings. Change your Module.Init:

public void Init(HttpApplication context) {
    _application = context;
    // change just this line:
    _application.PostAuthenticateRequest += ApplicationAuthenticateRequest;
}

IMPORTANT UPDATE:

Please see this question -asked by starter again, depended on current question- for a second solution, if this one doesn't work.

Jigaboo answered 24/5, 2012 at 18:45 Comment(3)
Thanks for this answer; I was pulling my hair out trying to figure this one!Neutralization
@DavidKeaveny Thank you, but I have to tell you the solution has a problem yet. Search in king.net's questions, you can find a Q associated on this one that there is another problem with IIS, so I suggest a way him/her, that resolve the issue fine. Please look at king.net's questions, you will find it. Regards.Jigaboo
Thanks for the heads-up; I'll keep an eye open for the issue when I deploy.Neutralization

© 2022 - 2024 — McMap. All rights reserved.