ASP.NET MVC 操作过滤器中的身份验证状态
Authentication state in ASP.NET MVC ActionFilters
我有一个名称为 Log
的 ActionFilter,它会在用户登录网站时记录用户 ip 和其他详细信息,因此为了完成这项工作,我编写了以下代码:
public class Log : ActionFilterAttribute
{
public IAppUserManager UserManager { get; set; }
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var status = filterContext.Controller.TempData.Any(pair => pair.Key == "status" && (int)pair.Value == 200);
if (filterContext.HttpContext.User != null && filterContext.HttpContext.User.Identity.IsAuthenticated && status)
{
var logIp = new AddIpAddressDto()
{
Browser = filterContext.HttpContext.Request.GetBrowser(),
Ip = filterContext.HttpContext.Request.GetIp(),
Os = filterContext.HttpContext.Request.UserAgent.GetOs(),
UrlReferrer = filterContext.HttpContext.Request.UrlReferrer?.ToString(),
UserId = Guid.Parse(filterContext.HttpContext.User.Identity.GetUserId()),
UserName = filterContext.HttpContext.User.Identity.GetUserName(),
};
UserManager.Log(logIp);
}
base.OnResultExecuted(filterContext);
}
}
此代码在 filterContext.HttpContext.User.Identity.IsAuthenticated
为 true 时有效。
登录操作上的 Log
过滤器声明:
[AllowAnonymous]
[Route("sign-in", Name = "signInRoute")]
[HttpPost, ValidateAntiForgeryToken]
[Log]
public virtual async Task<ActionResult> Login(LoginDto login, string returnTo)
{
var signInStatus = await _signInManager
.PasswordSignInAsync(user.UserName, login.Password, login.RememberMe, true)
.ConfigureAwait(false);
switch (signInStatus) // is Success
{
case SignInStatus.Success:
TempData["status"] = 200;
return RedirectToLocal(returnTo);
case SignInStatus.LockedOut:
// todo return time of louckout
break;
case SignInStatus.RequiresVerification:
return RedirectToAction("ConfirmEmail");
case SignInStatus.Failure:
return View(CleanPassWordInLogin(login));
default:
throw new ArgumentOutOfRangeException();
}
}
登录操作工作正常并且 signInStatus
是 成功 但在执行操作后 IsAuthenticated
是 false。
为了解决这个问题,我尝试了以下项目:
二手HttpContext.Current.GetOwinContext();
在 IoC 中定义了以下代码 (StructureMap 4.5.2)
config.For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));
试过OnActionExecuted
,OnActionExecuting
,OnResultExecuting
在 Identity 2.0
中使用 IAuthenticationManager
如何解决这个问题?
执行SignInManager.PasswordSignInAsync
后,将创建包含用户信息的身份验证cookie。因此 User.Identity
信息将由身份验证 cookie 中的声明填充,这些声明尚未解析(此 cookie 将在对服务器的第二个请求中解析,而不是在同一个登录请求中解析)。这就是为什么不能在 PasswordSignInAsync
之后使用 User.Identity
的原因。在这一点上,您只有一个选项来查找 userId:
string userId = UserManager.FindByName(model.Email)?.Id;
我有一个名称为 Log
的 ActionFilter,它会在用户登录网站时记录用户 ip 和其他详细信息,因此为了完成这项工作,我编写了以下代码:
public class Log : ActionFilterAttribute
{
public IAppUserManager UserManager { get; set; }
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var status = filterContext.Controller.TempData.Any(pair => pair.Key == "status" && (int)pair.Value == 200);
if (filterContext.HttpContext.User != null && filterContext.HttpContext.User.Identity.IsAuthenticated && status)
{
var logIp = new AddIpAddressDto()
{
Browser = filterContext.HttpContext.Request.GetBrowser(),
Ip = filterContext.HttpContext.Request.GetIp(),
Os = filterContext.HttpContext.Request.UserAgent.GetOs(),
UrlReferrer = filterContext.HttpContext.Request.UrlReferrer?.ToString(),
UserId = Guid.Parse(filterContext.HttpContext.User.Identity.GetUserId()),
UserName = filterContext.HttpContext.User.Identity.GetUserName(),
};
UserManager.Log(logIp);
}
base.OnResultExecuted(filterContext);
}
}
此代码在 filterContext.HttpContext.User.Identity.IsAuthenticated
为 true 时有效。
登录操作上的 Log
过滤器声明:
[AllowAnonymous]
[Route("sign-in", Name = "signInRoute")]
[HttpPost, ValidateAntiForgeryToken]
[Log]
public virtual async Task<ActionResult> Login(LoginDto login, string returnTo)
{
var signInStatus = await _signInManager
.PasswordSignInAsync(user.UserName, login.Password, login.RememberMe, true)
.ConfigureAwait(false);
switch (signInStatus) // is Success
{
case SignInStatus.Success:
TempData["status"] = 200;
return RedirectToLocal(returnTo);
case SignInStatus.LockedOut:
// todo return time of louckout
break;
case SignInStatus.RequiresVerification:
return RedirectToAction("ConfirmEmail");
case SignInStatus.Failure:
return View(CleanPassWordInLogin(login));
default:
throw new ArgumentOutOfRangeException();
}
}
登录操作工作正常并且 signInStatus
是 成功 但在执行操作后 IsAuthenticated
是 false。
为了解决这个问题,我尝试了以下项目:
二手
HttpContext.Current.GetOwinContext();
在 IoC 中定义了以下代码 (StructureMap 4.5.2)
config.For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));
试过
OnActionExecuted
,OnActionExecuting
,OnResultExecuting
在 Identity 2.0
中使用IAuthenticationManager
如何解决这个问题?
执行SignInManager.PasswordSignInAsync
后,将创建包含用户信息的身份验证cookie。因此 User.Identity
信息将由身份验证 cookie 中的声明填充,这些声明尚未解析(此 cookie 将在对服务器的第二个请求中解析,而不是在同一个登录请求中解析)。这就是为什么不能在 PasswordSignInAsync
之后使用 User.Identity
的原因。在这一点上,您只有一个选项来查找 userId:
string userId = UserManager.FindByName(model.Email)?.Id;