在 MVC3 中使用自定义 IPrincipal 和 IIdentity



我创建了自己的IPrincipalIIdentity实现,如下所示:

[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; }
    }
}

另外,我创建了一个HttpModule,并在其AuthenticateRequest事件中执行以下操作:

    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;
    }

此外,我创建了自己的Controller,并WebViewPage如下:

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;
        }
    }
}

如上面的代码所示,似乎一切都是正确的;但如您所见,在 1 号地方我无法访问CustomPrincipal!意味着在这个地方,我有一个RolePrincipal而不是一个CustomPrincipal.例如 HttpContext.Current.UserRolePrincipal而不是CustomPrincipal。但是RolePrincipal.Identity属性是一个CustomIdentity

你的错误在这里:

_application.AuthenticateRequest += ApplicationAuthenticateRequest;

有一个名为 RoleManagerModuleHttpModule,它调用 HttpApplication.PostAuthenticateRequest 中的方法并将HttpContext.Current.User设置为 RolePrincipal 。因此,您在AuthenticateRequest中设置了User,而RoleManagerModule将其设置为PostAuthenticateRequest,表示在您设置之后,因此会覆盖您的设置。更改您的Module.Init

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

重要更新:

请参阅此问题 - 由初学者再次提出,取决于当前问题 - 如果这个问题不起作用,则进行第二个解决方案。

最新更新