使用 Asp.Net 5 Identity 3.0 注销后未删除 Cookie
Cookie not deleted after logout with Asp.Net 5 Identity 3.0
我有一个 Asp.Net MVC 应用程序(版本 6.0.0-rc1-final),带有自定义角色和用户存储。经过一些 我终于可以创建一个有效的登录机制。但是,我现在确实无法创建干净的注销。我在控制器中的注销代码目前是什么样子的:
public async Task<ActionResult> Logout()
{
if (User.Identity.IsAuthenticated)
{
await SignInManager.SignOutAsync();
}
return RedirectToAction("Index", "App");
}
这段代码的问题是,一个 cookie 没有被删除:.AspNet.Microsoft.AspNet.Identity.Application
只要我不手动删除 cookie,应用程序就会处于脏状态并抛出空指针异常,因为 User.Identity 为空。
我发现 question on Whosebug 描述了类似的场景。但是那里的解决方案不适合我,因为我使用的 MVC 6 不再有 System.Web。
我也有一个示例解决方案,效果很好。在此解决方案中,永远不会创建提到的 cookie。也许正确的解决方案不是在注销后删除 cookie,而是以某种方式阻止创建 cookie。
我可以通过在注销操作后手动删除 cookie 来修复注销后应用程序的脏状态:
public async Task<ActionResult> Logout()
{
if (User.Identity.IsAuthenticated)
{
await SignInManager.SignOutAsync();
}
foreach (var key in HttpContext.Request.Cookies.Keys)
{
HttpContext.Response.Cookies.Append(key, "", new CookieOptions() { Expires = DateTime.Now.AddDays(-1) });
}
return RedirectToAction("Index", "App");
}
由于无法直接从服务器删除 cookie,我只是用已经过期的 cookie 覆盖现有的 cookie。
问题是您的 RedirectToAction
覆盖了 SignOutAsync
发出的到 Identity Server endsession URL 的重定向。
(微软的HaoKhere对同一问题给出了相同的解释。)
编辑:解决方案是在 AuthenticationProperties
对象中发送重定向 URL,最终 SignOutAsync
:
// in some controller/handler, notice the "bare" Task return value
public async Task LogoutAction()
{
// SomeOtherPage is where we redirect to after signout
await MyCustomSignOut("/SomeOtherPage");
}
// probably in some utility service
public async Task MyCustomSignOut(string redirectUri)
{
// inject IHttpContextAccessor to get "context"
await context.SignOutAsync("Cookies");
var prop = new AuthenticationProperties()
{
RedirectUri = redirectUri
});
// after signout this will redirect to your provided target
await context.SignOutAsync("oidc", prop);
}
除了已经提到的所有内容之外,还要确保在对 SignInAsync
和 SignOutAsync
的调用中没有省略 scheme
参数,并且传递相同的值二者皆是。例如:
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
和
HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
所以在这个例子中方案是CookieAuthenticationDefaults.AuthenticationScheme
。就我而言,我忘记将其传递给 SignOutAsync
,虽然事后显而易见,但我花了比我愿意承认的时间更长的时间来追踪。
另一个可能会在客户端留下身份服务器 cookie 的陷阱是注销失败。注销失败的一个典型原因是客户端的 PostLogoutRedirectUris 配置错误。
从客户端看不到注销失败,endsession
调用 returns 200 OK,以及 logout
调用。
然而,在您的身份服务器日志中会有注销失败的痕迹。
我有一个 Asp.Net MVC 应用程序(版本 6.0.0-rc1-final),带有自定义角色和用户存储。经过一些
public async Task<ActionResult> Logout()
{
if (User.Identity.IsAuthenticated)
{
await SignInManager.SignOutAsync();
}
return RedirectToAction("Index", "App");
}
这段代码的问题是,一个 cookie 没有被删除:.AspNet.Microsoft.AspNet.Identity.Application
只要我不手动删除 cookie,应用程序就会处于脏状态并抛出空指针异常,因为 User.Identity 为空。
我发现 question on Whosebug 描述了类似的场景。但是那里的解决方案不适合我,因为我使用的 MVC 6 不再有 System.Web。
我也有一个示例解决方案,效果很好。在此解决方案中,永远不会创建提到的 cookie。也许正确的解决方案不是在注销后删除 cookie,而是以某种方式阻止创建 cookie。
我可以通过在注销操作后手动删除 cookie 来修复注销后应用程序的脏状态:
public async Task<ActionResult> Logout()
{
if (User.Identity.IsAuthenticated)
{
await SignInManager.SignOutAsync();
}
foreach (var key in HttpContext.Request.Cookies.Keys)
{
HttpContext.Response.Cookies.Append(key, "", new CookieOptions() { Expires = DateTime.Now.AddDays(-1) });
}
return RedirectToAction("Index", "App");
}
由于无法直接从服务器删除 cookie,我只是用已经过期的 cookie 覆盖现有的 cookie。
问题是您的 RedirectToAction
覆盖了 SignOutAsync
发出的到 Identity Server endsession URL 的重定向。
(微软的HaoKhere对同一问题给出了相同的解释。)
编辑:解决方案是在 AuthenticationProperties
对象中发送重定向 URL,最终 SignOutAsync
:
// in some controller/handler, notice the "bare" Task return value
public async Task LogoutAction()
{
// SomeOtherPage is where we redirect to after signout
await MyCustomSignOut("/SomeOtherPage");
}
// probably in some utility service
public async Task MyCustomSignOut(string redirectUri)
{
// inject IHttpContextAccessor to get "context"
await context.SignOutAsync("Cookies");
var prop = new AuthenticationProperties()
{
RedirectUri = redirectUri
});
// after signout this will redirect to your provided target
await context.SignOutAsync("oidc", prop);
}
除了已经提到的所有内容之外,还要确保在对 SignInAsync
和 SignOutAsync
的调用中没有省略 scheme
参数,并且传递相同的值二者皆是。例如:
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
和
HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
所以在这个例子中方案是CookieAuthenticationDefaults.AuthenticationScheme
。就我而言,我忘记将其传递给 SignOutAsync
,虽然事后显而易见,但我花了比我愿意承认的时间更长的时间来追踪。
另一个可能会在客户端留下身份服务器 cookie 的陷阱是注销失败。注销失败的一个典型原因是客户端的 PostLogoutRedirectUris 配置错误。
从客户端看不到注销失败,endsession
调用 returns 200 OK,以及 logout
调用。
然而,在您的身份服务器日志中会有注销失败的痕迹。