使用 Asp.Net 5 身份 3.0 注销后不会删除 Cookie

本文关键字:删除 Cookie 注销 Net Asp 身份 使用 | 更新日期: 2023-09-27 18:31:20

我确实有一个带有自定义角色和用户存储的 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为空。

我发现了一个关于堆栈溢出的问题,描述了类似的场景。但是那里的解决方案不适合我,因为我使用的是不再具有System.Web的MVC 6。

我还有一个示例解决方案,可以正常工作。在此解决方案中,永远不会创建提到的cookie。也许正确的解决方案不是在注销后删除cookie,而是以某种方式防止cookie的创建。

使用 Asp.Net 5 身份 3.0 注销后不会删除 Cookie

问题是您的RedirectToAction覆盖了重定向到SignOutAsync问题的身份服务器结束会话 URL。

(Microsoft的HaoK对同一问题给出了相同的解释。

编辑:解决方案是在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);
}

我可以通过在注销操作后手动删除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。

除了已经提到的所有内容之外,还要确保在调用 SignInAsyncSignOutAsync 时没有省略 scheme 参数,并且将相同的值传递给两者。例如:

HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

所以在这个例子中,方案是CookieAuthenticationDefaults.AuthenticationScheme .就我而言,我忘记将此传递给SignOutAsync,虽然事后很明显,但我花了比我愿意承认的时间更长的时间才能追踪。

另一个可能将身份服务器 cookie 保留在客户端上的问题是注销失败。注销失败的一个典型原因是客户端的 PostLogoutRedirectUri 配置错误。

注销失败在客户端不可见,endsession调用返回 200 OK 以及logout调用。

但是,您的身份服务器日志上会跟踪注销失败。