自定义标识使用MVC5和OWIN [英] Custom Identity using MVC5 and OWIN

查看:327
本文介绍了自定义标识使用MVC5和OWIN的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想自定义属性添加到ApplicationUser使用MVC5和OWIN身份验证的网站。我读过 http://stackoverflow.com/a/10524305/264607 ,我喜欢它如何与底座集成控制器容易获得新的属性。我的问题是,当我设置HTTPContext.Current.User属性为我的新的IPrincipal我得到一个空引用错误:

I trying to add custom properties to the ApplicationUser for a web site using MVC5 and OWIN authentication. I've read http://stackoverflow.com/a/10524305/264607 and I like how it integrates with the base controller for easy access to the new properties. My issue is that when I set the HTTPContext.Current.User property to my new IPrincipal I get a null reference error:

[NullReferenceException: Object reference not set to an instance of an object.]
   System.Web.Security.UrlAuthorizationModule.OnEnter(Object source, EventArgs eventArgs) +127
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

下面是我的code:

    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

            ApplicationUser user = userManager.FindByName(HttpContext.Current.User.Identity.Name);

            PatientPortalPrincipal newUser = new PatientPortalPrincipal();
            newUser.BirthDate = user.BirthDate;
            newUser.InvitationCode = user.InvitationCode;
            newUser.PatientNumber = user.PatientNumber;

            //Claim cPatient = new Claim(typeof(PatientPortalPrincipal).ToString(), );

            HttpContext.Current.User = newUser;
        }
    }

public class PatientPortalPrincipal : ClaimsPrincipal, IPatientPortalPrincipal
{
    public PatientPortalPrincipal(ApplicationUser user)
    {
        Identity = new GenericIdentity(user.UserName);
        BirthDate = user.BirthDate;
        InvitationCode = user.InvitationCode;
    }

    public PatientPortalPrincipal() { }

    public new bool IsInRole(string role)
    {
        if(!string.IsNullOrWhiteSpace(role))
            return Role.ToString().Equals(role);

        return false;
    }

    public new IIdentity Identity { get; private set; }
    public WindowsBuiltInRole Role { get; set; }
    public DateTime BirthDate { get; set; }
    public string InvitationCode { get; set; }
    public string PatientNumber { get; set; }
}

public interface IPatientPortalPrincipal : IPrincipal
{

    WindowsBuiltInRole Role { get; set; }
    DateTime BirthDate { get; set; }
    string InvitationCode { get; set; }
    string PatientNumber { get; set; }
}

我没有找到如何做到这一点的文档的方式很多,我读过这些文章:

I haven't found much in the way of documentation on how to do this, I've read these articles:

<一个href=\"http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx\">http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx

<一个href=\"http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-forms-authentication-in-mvc-5.aspx\">http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-forms-authentication-in-mvc-5.aspx

在第二个链接的评论中指出我也许使用要求(<一个href=\"http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp\">http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp) ,但联系到文章不显示如何添加这些到的IPrincipal (这是 HttpContext.Current.User 是),或在管道中你应该将它们添加到 ClaimsIdentity (这是水泥类用户的)。我倾向于使用的主张,但我需要知道这些新的要求添加到用户。

The comments in the second link pointed me to perhaps using claims (http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp) , but the article linked to doesn't show how to add those to an IPrincipal (which is what HttpContext.Current.User is), or where in the pipeline you're supposed to add them to a ClaimsIdentity (which is the concrete class the User is). I'm leaning towards using claims, but I need to know where to add these new claims to the user.

即使索赔是要走的路,我很好奇,我和我的自定义的IPrincipal做错了什么,因为我似乎有它需要实现的事情。

Even if claims are the way to go, I'm curious as to what I'm doing wrong with my custom IPrincipal, as I seem to have implemented everything it requires.

推荐答案

我能得到的东西使用基于声明安全工作,所以如果你想要得到的东西完成快速这里是我目前所面对的:

I can get something to work using Claims based security, so if you're looking to get something done quickly here is what I have at the moment:

的AccountController 登录过程中(我的是 SignInAsync 方法内),添加一个新的索赔到通过的UserManager 创建身份:

In the login process in the AccountController (mine is within SignInAsync method), add a new claim to the identity created by UserManager:

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    identity.AddClaim(new Claim("PatientNumber", user.PatientNumber)); //This is what I added
    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

然后在我的基本控制器类我只是增加一个属性:

Then in my base controller classes I simply added a property:

private string _patientNumber;
public string PatientNumber
{
    get
    {
        if (string.IsNullOrWhiteSpace(_patientNumber))
        {
            try
            {
                var cp = ClaimsPrincipal.Current.Identities.First();
                var patientNumber = cp.Claims.First(c => c.Type == "PatientNumber").Value;
                _patientNumber = patientNumber;
            }
            catch (Exception)
            {
            }
        }
        return _patientNumber;
    }
}

这是链接索赔知识有所帮助:<一href=\"http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp#$c$c-snippet-1\">http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp#$c$c-snippet-1

This link was helpful for claims knowledge: http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

更新与IPrincipal的问题

Update for the issue with IPrincipal

我跟踪它到的身份属性。问题是,我提供关于 PatientPortalPrincipal 类,并没有设置身份属性的默认构造函数。我最终什么了做取出了默认的构造函数调用,并从正确的构造函数中 Application_PostAuthenticateRequest ,更新code是低于

I tracked it down to the Identity property. The issue was that I was providing a default constructor on the PatientPortalPrincipal class that was not setting the Identity property. What I ended up doing was removing the default constructor and calling the correct constructor from within Application_PostAuthenticateRequest, updated code is below

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

        ApplicationUser user = userManager.FindByName(HttpContext.Current.User.Identity.Name);

        PatientPortalPrincipal newUser = new PatientPortalPrincipal(user);
        newUser.BirthDate = user.BirthDate;
        newUser.InvitationCode = user.InvitationCode;
        newUser.PatientNumber = user.PatientNumber;

        //Claim cPatient = new Claim(typeof(PatientPortalPrincipal).ToString(), );

        HttpContext.Current.User = newUser;
    }
}

这使得整个事情的工作!

That makes the whole thing work!

这篇关于自定义标识使用MVC5和OWIN的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆