自定义标识使用MVC5和OWIN [英] Custom Identity using MVC5 and 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屋!