OWIN 身份验证成功但 User.Identity.IsAuthenticated 为假
OWIN authentication succeeds but User.Identity.IsAuthenticated is false
我开发了一个使用 OWIN 身份验证的站点。一切正常,但突然间,没有任何代码更改,站点身份验证停止工作。当我输入用户名和密码时,对 SignInManager.PasswordSignInAsync
的调用成功但 User.Identity.IsAuthenticated
仍然是 false
。
这是Startup.Auth.cs:
public partial class Startup
{
// For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
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))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
}
}
这里是进行身份验证的地方:
public override Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
var result = base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout).Result;
if (result == SignInStatus.Success)
{
ApplicationUser user = this.UserManager.FindAsync(userName, password).Result;
user.LastLoggedOn = DateTime.Now;
if (!user.FirstLoggedOn.HasValue)
user.FirstLoggedOn = user.LastLoggedOn;
this.UserManager.UpdateAsync(user);
}
return Task.FromResult(result);
}
有一点要注意。我在其他站点和所有身份验证中使用完全相同的代码。只有一个网站有这个问题。
这是Accountcontroller的登录方法:
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
var mensaje = GetModelErrorMessages();
return Json(mensaje, JsonRequestBehavior.AllowGet);
}
if (String.IsNullOrEmpty(returnUrl))
returnUrl = "/";
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return Json(returnUrl, JsonRequestBehavior.AllowGet);
case SignInStatus.LockedOut:
return Json("ERROR: El usuario está bloqueado.", JsonRequestBehavior.AllowGet);
case SignInStatus.RequiresVerification:
return Json(Url.Action("SendCode", new { ReturnUrl = returnUrl, model.RememberMe }));
case SignInStatus.Failure:
default:
var mensaje = "ERROR: Nombre de usuario o contraseña incorrectos.";
return Json(mensaje, JsonRequestBehavior.AllowGet);
}
}
如您所见,这 returns JSON。 JSON 包含用于重定向到其他 URL 的 return url,如该脚本所示:
function performLogin(loginUrl)
{
runWaitMe('#loginform', "Ingresando...");
$.ajax({
type: 'POST',
url: loginUrl,
data: $('#frmLogin').serialize()
}).done(function (data) {
if (displayError(data))
hideWaitMe('#loginform');
else
location.href = data;
}).fail(function (jqXHR) {
hideWaitMe('#loginform');
showError(jqXHR);
});
}
我再说一遍,同样的代码在我开发的所有网站中都适用,并且适用于所有网站。
也许对于这种情况,cookie 无法保存。
我可以检查什么?
问候
海梅
事实证明,即使身份验证成功,User.Identity.IsAuthenticated
在下一次请求之前仍然为假。
如果我打算用 User.Identity.IsAuthenticated
属性 做一些事情,我需要做一个重定向。
检查你的cookie是否设置了secure参数,你的站点只有http。
我开发了一个使用 OWIN 身份验证的站点。一切正常,但突然间,没有任何代码更改,站点身份验证停止工作。当我输入用户名和密码时,对 SignInManager.PasswordSignInAsync
的调用成功但 User.Identity.IsAuthenticated
仍然是 false
。
这是Startup.Auth.cs:
public partial class Startup
{
// For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
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))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
}
}
这里是进行身份验证的地方:
public override Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
var result = base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout).Result;
if (result == SignInStatus.Success)
{
ApplicationUser user = this.UserManager.FindAsync(userName, password).Result;
user.LastLoggedOn = DateTime.Now;
if (!user.FirstLoggedOn.HasValue)
user.FirstLoggedOn = user.LastLoggedOn;
this.UserManager.UpdateAsync(user);
}
return Task.FromResult(result);
}
有一点要注意。我在其他站点和所有身份验证中使用完全相同的代码。只有一个网站有这个问题。
这是Accountcontroller的登录方法:
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
var mensaje = GetModelErrorMessages();
return Json(mensaje, JsonRequestBehavior.AllowGet);
}
if (String.IsNullOrEmpty(returnUrl))
returnUrl = "/";
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return Json(returnUrl, JsonRequestBehavior.AllowGet);
case SignInStatus.LockedOut:
return Json("ERROR: El usuario está bloqueado.", JsonRequestBehavior.AllowGet);
case SignInStatus.RequiresVerification:
return Json(Url.Action("SendCode", new { ReturnUrl = returnUrl, model.RememberMe }));
case SignInStatus.Failure:
default:
var mensaje = "ERROR: Nombre de usuario o contraseña incorrectos.";
return Json(mensaje, JsonRequestBehavior.AllowGet);
}
}
如您所见,这 returns JSON。 JSON 包含用于重定向到其他 URL 的 return url,如该脚本所示:
function performLogin(loginUrl)
{
runWaitMe('#loginform', "Ingresando...");
$.ajax({
type: 'POST',
url: loginUrl,
data: $('#frmLogin').serialize()
}).done(function (data) {
if (displayError(data))
hideWaitMe('#loginform');
else
location.href = data;
}).fail(function (jqXHR) {
hideWaitMe('#loginform');
showError(jqXHR);
});
}
我再说一遍,同样的代码在我开发的所有网站中都适用,并且适用于所有网站。
也许对于这种情况,cookie 无法保存。
我可以检查什么?
问候 海梅
事实证明,即使身份验证成功,User.Identity.IsAuthenticated
在下一次请求之前仍然为假。
如果我打算用 User.Identity.IsAuthenticated
属性 做一些事情,我需要做一个重定向。
检查你的cookie是否设置了secure参数,你的站点只有http。