我有一个使用Identity 2.0和Owin的应用程序.
我希望应用程序为默认用户播种并在开发时自动登录(我用#if DEBUG条件包装方法及其调用).
我尝试将以下方法添加到IdentityConfig.csApplicationUserManager.Create方法,但在调用它之后,HttpContext.Current.User在下次调用时仍为null.
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);
}
但它一直在不断地对用户进行身份验证.我确信应该有一个更合适的位置来执行这种自动化.
附:从Global.asax.cs或Startup.cs这样做是不可能的,因为owin在那个阶段尚未初始化.
我尝试在Context初始化程序中添加它,用户被创建,但登录失败.
更新
在this回答:
实际上,在IdentityConfig.cs类中无论如何都会覆盖UserManager.但我想的是,每次调用CustomAuthorize下的方法时,您的解决方案都会检查用户是否存在.而我只想在应用启动时执行默认用户创建和登录.
更新2
在我的数据库初始化程序中,我有一些关键的种子表,它们有与用户相关的数据,这意味着,我必须在种子方法中创建用户.所以现在我的问题是,当我手动创建用户时,如下代码:
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;
}
}
正如你所看到的,我甚至添加了一个静态成员来避免循环初始化器,但我相信它仍然无济于事.
因为当我尝试手动创建用户时(使用UserManager.PasswordHasher添加到Users表中,我无法登录该帐户).
但上面代码的问题是我从Seed调用它,我怀疑它在我尝试创建用户时会在内部调用它,然后它就会卡住.
我正在寻找的解决方案是如何手动创建用户并能够登录该帐户.我可能在密码散列/用户验证/其他任何问题上都缺少一点.
最佳答案 在默认的Autorization开始之前,您需要这样做.要做到这一点,最简单的方法是创建自己的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:
如果不想为每个请求登录,则可以跳过该请求,但仍需要从DB中获取用户.实现您的服务到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);
}