在 MVC3 中使用自定义 IPrincipal 和 IIdentity

Posted

技术标签:

【中文标题】在 MVC3 中使用自定义 IPrincipal 和 IIdentity【英文标题】:using custom IPrincipal and IIdentity in MVC3 【发布时间】:2012-05-31 07:38:49 【问题描述】:

我创建了自己的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;
    

另外,我创建了自己的 ControllerWebViewPage,如下所示:

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;
        
    

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

【问题讨论】:

【参考方案1】:

你的错误在这里:

_application.AuthenticateRequest += ApplicationAuthenticateRequest;

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

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

重要更新:

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

【讨论】:

感谢您的回答;我正在拔头发试图弄清楚这个! @DavidKeaveny 谢谢,但我必须告诉你解决方案还有问题。搜索king.net的问题,你可以找到一个与此相关的Q,表明IIS还有另一个问题,所以我建议他/她的一种方式,可以很好地解决问题。请看king.net的问题,你会找到的。问候。 感谢您的提醒;我会在部署时密切注意这个问题。

以上是关于在 MVC3 中使用自定义 IPrincipal 和 IIdentity的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET web api - 设置自定义 IIdentity 或 IPrincipal

在 MVC 中实现自定义身份和 IPrincipal

在 MVC3 中的 Ajax.Beginform 中调用自定义确认对话框

在 MVC3 应用程序中将 Ninject 与自定义角色提供程序一起使用

MVC3 自定义视图库

MVC 授权角色和 IPrincipal - 它是如何工作的?