在ASP.NET MVC5中,我使用ASP.NET身份,除了PasswordSignInAsync
之外,我必须通过向PasswordSignInAsync
添加ApplicationSignInManager
重载以及存储状态的附加属性来实现一些自定义登录规则:
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public EnumCompanyStatus CompanyStatus { get; private set; }
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager)
{
CompanyStatus = EnumCompanyStatus.Active;
}
// Standard scaffolding omitted
public async Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout, Func<string, EnumCompanyStatus> getCompanyStatus)
{
SignInStatus signInStatus = await base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout);
if (signInStatus == SignInStatus.Success)
{
CompanyStatus = getCompanyStatus(userName);
if (CompanyStatus != EnumCompanyStatus.Active)
signInStatus = SignInStatus.Failure;
}
return signInStatus;
}
}
这是我在AccountController
中的登录方法:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false, GetCompanyStatus);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
if (SignInManager.CompanyStatus == EnumCompanyStatus.Disabled)
ModelState.AddModelError("", "User disabled.");
else if (SignInManager.CompanyStatus == EnumCompanyStatus.Frozen)
ModelState.AddModelError("", "Please contact our support.");
else
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
我的问题在于default
声明中的switch/case
案例。每当SignInManager.CompanyStatus
是Disabled
或Frozen
时,这个相应的代码将被正确地访问,但是,大多数时候用户仍将被重定向到主页而不是让应用程序只打印我的错误消息。它已经工作了几次,但我的断点是阻碍了。如果执行到达最后一个条件,传统登录失败尝试,它完美地工作(错误消息显示在登录页面中,并且没有发生重定向),但.NET似乎对我对signInStatus
的搞乱感到不满意。我在这里错过了什么?我只能想象有另一个属性妨碍了我,但我多年来一直处理Web开发,我现在可以真正使用一些帮助。
在摸索了一下之后,我想是的,PasswordSignInAsync确实改变了一个内部状态,无论我之后做了什么都验证了我的请求。所以我只是交换了自定义验证和基本方法调用的顺序:
public async Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout, Func<string, EnumCompanyStatus> getCompanyStatus)
{
CompanyStatus = getCompanyStatus(userName);
if (CompanyStatus != EnumCompanyStatus.Active)
return SignInStatus.Failure;
return await base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout);
}