我试图使用MVC5和OWIN身份验证将自定义属性添加到网站的ApplicationUser中。我已经阅读了https://stackoverflow.com/a/10524305/264607,我喜欢它如何与基本控制器集成在一起以方便地访问新属性。我的问题是,当我将HTTPContext.Current.User属性设置为新的IPrincipal时,出现空引用错误:
[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
这是我的代码:
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; }
}
关于如何执行此操作的方法方面,我还没有发现太多,我已经阅读了以下文章:
第二个链接中的注释指示我可能使用了声明(http://msdn.microsoft.com/en-us/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp),但该文章已链接to不会显示如何将它们添加到IPrincipal
(HttpContext.Current.User
是),或者应该在管道中的何处将它们添加到ClaimsIdentity
(是is的具体类User
)。我倾向于使用声明,但是我需要知道将这些新声明添加到用户的位置。
即使可以使用声明,但我对自己的自定义IPrincipal做错了事感到好奇,因为我似乎已经实现了它所要求的一切。
我可以使用Claims
基于安全性的方法来使某些事情起作用,因此,如果您希望快速完成某件事,那么这就是我目前所拥有的:
在AccountController
(mine在SignInAsync
方法内)的登录过程中,向由创建的标识添加新的声明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);
}
然后,在我的基本控制器类中,我仅添加了一个属性:
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;
}
}
该链接对于理赔知识很有帮助:http : //msdn.microsoft.com/zh-cn/library/ms734687.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
有关IPrincipal的问题的更新
我将其追溯到该Identity
物业。问题是我PatientPortalPrincipal
在没有设置Identity属性的类上提供了默认构造函数。我最终要做的是删除默认构造函数,并从内部调用正确的构造函数Application_PostAuthenticateRequest
,更新后的代码如下
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;
}
}
这使整个工作正常!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句