EF 在 Owin 授权超时后抛出 AspNetUsers 错误
EF throws AspNetUsers error after Owin Authorization timeout
我在 AccountController
中覆盖了 MVC5
应用程序的授权。它可以正常登录和注销,获取上下文等。但是,如果授权超时,它不会将我重定向回 Login
页面,而是抛出错误:
Invalid object name 'dbo.AspNetUsers'.
我没有在身份验证中使用 EF
,而是使用服务,所以我没有这些表。但是,我找不到它在哪里命中此代码以引发错误。
AccountController.cs:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var userRequest = new RequestObject
{
Name = model.Username,
Password = model.Password
};
try
{
var result = await client.LoginUserAsync(userRequest);
if (result == 0)
{
var user = new User
{
Name = model.Username
};
OwinSignIn(user);
return RedirectToAction("Index", "Home");
}
}
catch (Exception)
{
// TODO: log error
}
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
private void OwinSignIn(User user, bool isPersistence = false)
{
var claims = new[] {
new Claim(ClaimTypes.Name, user.Name)
};
var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
var result = client.GetUserRoles(userRequest);
var roles = result.Roles.ToList();
if (roles.Any())
{
var roleClaims = roles.Select(r => new Claim(ClaimTypes.Role, r.Name));
identity.AddClaims(roleClaims);
}
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistence }, identity);
}
同样,这 仅 在我登录并等待该授权过期时发生。我不确定我没有更新什么方法以确保它返回到 Login
页面 - 我怀疑有什么东西正在检查会话在某处是否仍然有效但我不确定在哪里.
谢谢。
更新:
如果我删除 OnValidateIdentity
调用,问题就会消失。我不确定这是否可以修复或者是否可以删除它...
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
我了解到您已经找到了解决问题的方法。如果您不使用 EF 来保留您的用户数据,那么从您的解决方案中删除大部分身份包并仅保留必需的 OWIN 包是安全的。
你看到这个效果的原因是因为这个位:
OnValidateIdentity =
SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
每30分钟根据请求执行一次,检查当前cookie是否与数据库中的数据相同。实际上是调用默认 ApplicationUserManager
,默认情况下连接到 EF,默认情况下期望 AspNetUsers
table 存在。不,您不会在您的解决方案中找到此字符串 - 此 table 是在 IdentityDbContext
上定义的,由身份的 EF 部分提供。
我怀疑让你的 ApplicationDbContext
继承自 DbContext
而不是继承自 IdentityDbContext
是安全的 - 这将消除任何命中丢失 table 的可能性你不需要的。之后您可以删除 ApplicationUserManager
(因为它期望 IdentityDbContext
)。
我 blogged 关于使用 AD 作为设置 OWIN cookie 的服务 - 其中一些可能对您有用。
我在 AccountController
中覆盖了 MVC5
应用程序的授权。它可以正常登录和注销,获取上下文等。但是,如果授权超时,它不会将我重定向回 Login
页面,而是抛出错误:
Invalid object name 'dbo.AspNetUsers'.
我没有在身份验证中使用 EF
,而是使用服务,所以我没有这些表。但是,我找不到它在哪里命中此代码以引发错误。
AccountController.cs:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var userRequest = new RequestObject
{
Name = model.Username,
Password = model.Password
};
try
{
var result = await client.LoginUserAsync(userRequest);
if (result == 0)
{
var user = new User
{
Name = model.Username
};
OwinSignIn(user);
return RedirectToAction("Index", "Home");
}
}
catch (Exception)
{
// TODO: log error
}
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
private void OwinSignIn(User user, bool isPersistence = false)
{
var claims = new[] {
new Claim(ClaimTypes.Name, user.Name)
};
var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
var result = client.GetUserRoles(userRequest);
var roles = result.Roles.ToList();
if (roles.Any())
{
var roleClaims = roles.Select(r => new Claim(ClaimTypes.Role, r.Name));
identity.AddClaims(roleClaims);
}
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistence }, identity);
}
同样,这 仅 在我登录并等待该授权过期时发生。我不确定我没有更新什么方法以确保它返回到 Login
页面 - 我怀疑有什么东西正在检查会话在某处是否仍然有效但我不确定在哪里.
谢谢。
更新:
如果我删除 OnValidateIdentity
调用,问题就会消失。我不确定这是否可以修复或者是否可以删除它...
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
我了解到您已经找到了解决问题的方法。如果您不使用 EF 来保留您的用户数据,那么从您的解决方案中删除大部分身份包并仅保留必需的 OWIN 包是安全的。
你看到这个效果的原因是因为这个位:
OnValidateIdentity =
SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
每30分钟根据请求执行一次,检查当前cookie是否与数据库中的数据相同。实际上是调用默认 ApplicationUserManager
,默认情况下连接到 EF,默认情况下期望 AspNetUsers
table 存在。不,您不会在您的解决方案中找到此字符串 - 此 table 是在 IdentityDbContext
上定义的,由身份的 EF 部分提供。
我怀疑让你的 ApplicationDbContext
继承自 DbContext
而不是继承自 IdentityDbContext
是安全的 - 这将消除任何命中丢失 table 的可能性你不需要的。之后您可以删除 ApplicationUserManager
(因为它期望 IdentityDbContext
)。
我 blogged 关于使用 AD 作为设置 OWIN cookie 的服务 - 其中一些可能对您有用。