使用 ASP.NET MVC Identity 2.0 播种和登录默认用户的合适位置在哪里?
Where is the appropriate spot to seed and login a default user with ASP.NET MVC Identity 2.0?
我有一个使用 Identity 2.0 和 Owin 的应用程序。
我希望应用程序在开发过程中为默认用户设定种子并自动登录(我用 #if DEBUG
条件包装方法及其调用)。
我尝试将以下方法添加到 IdentityConfig.csApplicationUserManager.Create
方法中,但是在调用它之后, HttpContext.Current.User
仍然是空的打电话。
private void SeedAndLoginDefaultUser()
{
var user = this.FindByName("***");
if (user == null)
this.Create(new ApplicationUser { /* ... */ }, "***");
using (var signInManager = new ApplicationSignInManager(this,
HttpContext.Current.GetOwinContext().Authentication))
signInManager.PasswordSignIn(user.UserName, "***", true, false);
}
但它不断地对用户进行身份验证。我确定应该有一个更合适的位置来执行此自动化操作。
P.S。从 Global.asax.cs 或 Startup.cs 做是不可能的,因为 owin 在那个阶段还没有初始化。
我尝试将其添加到 Context 初始化程序中,创建了用户,但登录失败。
更新
在 上回答:
实际上,UserManager 在 IdentityConfig.cs class 中被覆盖了。但我在想的是,每次调用 CustomAuthorize
下的方法时,您的解决方案都会检查用户是否存在。而我只想在应用程序启动时执行默认用户创建和登录。
更新 2
在我的数据库初始化程序中,我有一些关键的种子 tables,它有与用户相关的数据,这意味着,我必须在种子方法中创建用户。所以我现在的问题是,当我按照以下代码手动创建用户时:
public class Initializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
private static volatile bool processing;
protected override void Seed(ApplicationDbContext context)
{
if (processing)
return;
processing = true;
using (var um = ApplicationUserManager.Get())
{
var shimmy = new ApplicationUser
{
//Id = Guid.NewGuid().ToString(),
FirstName = "Shimmy",
LastName = "Weitzhandler",
UserName = "***",
Email = "***",
//EmailConfirmed = true,
};
var task = um.CreateAsync(shimmy, "***");
task.Wait();
var result = task.Result;
if (result.Succeeded)
{
using (var sm = ApplicationSignInManager.Get())
{
var siTask = sm.SignInAsync(shimmy, true, true);
siTask.Wait();
if (siTask.Exception != null)
{
throw siTask.Exception;
}
}
}
else
{
throw new InvalidOperationException();
}
}
//seed my tables
processing = false;
}
}
如您所见,我什至添加了一个静态成员来避免循环返回初始化程序,但我相信它仍然无济于事。
因为当我尝试手动创建用户时(添加到 Users
table,使用 UserManager.PasswordHasher
,我无法登录该帐户。
但是上面代码的问题是我从 Seed
调用它,我怀疑当我尝试创建用户时它在内部回调自己,然后它卡住了。
我正在寻找的解决方案是如何手动创建用户并能够登录到该帐户。我可能在密码散列/用户验证/其他方面遗漏了一些要点。
您需要在默认授权开始之前执行此操作。为此,最简单的方法是创建您自己的 AuthorizeAttribute。
public class MyCustomAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
#if DEBUG
return true;
#else
return base.AuthorizeCore(httpContext);
}
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
#if DEBUG
// CHANGE TO YOUR USER MANAGER
var userManger = filterContext.HttpContext.GetOwinContext().GetUserManager<ApplicationUser>();
var user = userManger.FindByName("***");
if (user == null)
this.Create(new ApplicationUser {/* ... */}, "***");
using(var signInManager = new ApplicationSignInManager(userManger, filterContext.HttpContext.GetOwinContext().Authentication))
signInManager.PasswordSignIn(user.UserName, "***", true, false);
return;
#endif
return base.OnAuthorization(filterContext);
}
}
然后将所有现有的 Authorize 属性替换为您自己的属性,即
[MyCustomAuthorize]
[MyCustomAuthorize(Roles = "ROLENAME")]
解决方案 2:
如果不想为每个请求都登录,你可以跳过它,但你仍然需要从数据库中获取用户。为 getUser 实现您的服务。否则,您可以使用名称和角色(如有必要)对用户进行硬编码。
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
#if DEBUG
// CHANGE TO YOUR USER MANAGER
var user = GETUSER("");
var principal = new GenericPrincipal(new GenericIdentity(user.Name), new[] { user.RoleName });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return;
#endif
return base.OnAuthorization(filterContext);
}
我有一个使用 Identity 2.0 和 Owin 的应用程序。
我希望应用程序在开发过程中为默认用户设定种子并自动登录(我用 #if DEBUG
条件包装方法及其调用)。
我尝试将以下方法添加到 IdentityConfig.csApplicationUserManager.Create
方法中,但是在调用它之后, HttpContext.Current.User
仍然是空的打电话。
private void SeedAndLoginDefaultUser()
{
var user = this.FindByName("***");
if (user == null)
this.Create(new ApplicationUser { /* ... */ }, "***");
using (var signInManager = new ApplicationSignInManager(this,
HttpContext.Current.GetOwinContext().Authentication))
signInManager.PasswordSignIn(user.UserName, "***", true, false);
}
但它不断地对用户进行身份验证。我确定应该有一个更合适的位置来执行此自动化操作。
P.S。从 Global.asax.cs 或 Startup.cs 做是不可能的,因为 owin 在那个阶段还没有初始化。
我尝试将其添加到 Context 初始化程序中,创建了用户,但登录失败。
更新
在
实际上,UserManager 在 IdentityConfig.cs class 中被覆盖了。但我在想的是,每次调用 CustomAuthorize
下的方法时,您的解决方案都会检查用户是否存在。而我只想在应用程序启动时执行默认用户创建和登录。
更新 2
在我的数据库初始化程序中,我有一些关键的种子 tables,它有与用户相关的数据,这意味着,我必须在种子方法中创建用户。所以我现在的问题是,当我按照以下代码手动创建用户时:
public class Initializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
private static volatile bool processing;
protected override void Seed(ApplicationDbContext context)
{
if (processing)
return;
processing = true;
using (var um = ApplicationUserManager.Get())
{
var shimmy = new ApplicationUser
{
//Id = Guid.NewGuid().ToString(),
FirstName = "Shimmy",
LastName = "Weitzhandler",
UserName = "***",
Email = "***",
//EmailConfirmed = true,
};
var task = um.CreateAsync(shimmy, "***");
task.Wait();
var result = task.Result;
if (result.Succeeded)
{
using (var sm = ApplicationSignInManager.Get())
{
var siTask = sm.SignInAsync(shimmy, true, true);
siTask.Wait();
if (siTask.Exception != null)
{
throw siTask.Exception;
}
}
}
else
{
throw new InvalidOperationException();
}
}
//seed my tables
processing = false;
}
}
如您所见,我什至添加了一个静态成员来避免循环返回初始化程序,但我相信它仍然无济于事。
因为当我尝试手动创建用户时(添加到 Users
table,使用 UserManager.PasswordHasher
,我无法登录该帐户。
但是上面代码的问题是我从 Seed
调用它,我怀疑当我尝试创建用户时它在内部回调自己,然后它卡住了。
我正在寻找的解决方案是如何手动创建用户并能够登录到该帐户。我可能在密码散列/用户验证/其他方面遗漏了一些要点。
您需要在默认授权开始之前执行此操作。为此,最简单的方法是创建您自己的 AuthorizeAttribute。
public class MyCustomAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
#if DEBUG
return true;
#else
return base.AuthorizeCore(httpContext);
}
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
#if DEBUG
// CHANGE TO YOUR USER MANAGER
var userManger = filterContext.HttpContext.GetOwinContext().GetUserManager<ApplicationUser>();
var user = userManger.FindByName("***");
if (user == null)
this.Create(new ApplicationUser {/* ... */}, "***");
using(var signInManager = new ApplicationSignInManager(userManger, filterContext.HttpContext.GetOwinContext().Authentication))
signInManager.PasswordSignIn(user.UserName, "***", true, false);
return;
#endif
return base.OnAuthorization(filterContext);
}
}
然后将所有现有的 Authorize 属性替换为您自己的属性,即
[MyCustomAuthorize]
[MyCustomAuthorize(Roles = "ROLENAME")]
解决方案 2:
如果不想为每个请求都登录,你可以跳过它,但你仍然需要从数据库中获取用户。为 getUser 实现您的服务。否则,您可以使用名称和角色(如有必要)对用户进行硬编码。
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
#if DEBUG
// CHANGE TO YOUR USER MANAGER
var user = GETUSER("");
var principal = new GenericPrincipal(new GenericIdentity(user.Name), new[] { user.RoleName });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return;
#endif
return base.OnAuthorization(filterContext);
}