【问题标题】:HttpContext.SignOutAsync() neither logs out the user nor deletes the local cookieHttpContext.SignOutAsync() 既不注销用户也不删除本地cookie
【发布时间】:2019-06-10 20:02:40
【问题描述】:

我知道已经有关于这个主题的问题,但给定的答案都不适用于我的情况。

这是核心:

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<comedyContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options => {
                options.LoginPath = "/login/";
            });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseAuthentication();

        app.UseMvc();
    }

Login.cshtml.cs

    public class LoginModel : PageModel
{
    [BindProperty]
    public string inputUsername { get; set; }
    [BindProperty]
    public string inputPassword { get; set; }

    private readonly comedyContext _context;

    public LoginModel(comedyContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> OnPostAsync()
    {
        var user = await _context.User.FirstOrDefaultAsync(u =>
            string.Equals(u.Username, inputUsername, StringComparison.CurrentCultureIgnoreCase) && string.Equals(u.Password, Utility.sha256_hash(inputPassword), StringComparison.CurrentCultureIgnoreCase));

        if (user is null)
            return Redirect("/login");

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.UserId.ToString()),
            new Claim(ClaimTypes.Name, inputUsername)
        };

        var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

        var authProperties = new AuthenticationProperties
        {
            AllowRefresh = true,
            // Refreshing the authentication session should be allowed.

            ExpiresUtc = DateTimeOffset.UtcNow.AddHours(24),
            // The time at which the authentication ticket expires. A 
            // value set here overrides the ExpireTimeSpan option of 
            // CookieAuthenticationOptions set with AddCookie.

            IsPersistent = true,
            // Whether the authentication session is persisted across 
            // multiple requests. Required when setting the 
            // ExpireTimeSpan option of CookieAuthenticationOptions 
            // set with AddCookie. Also required when setting 
            // ExpiresUtc.

            IssuedUtc = DateTimeOffset.UtcNow,
            // The time at which the authentication ticket was issued.

            //RedirectUri = <string>
            // The full path or absolute URI to be used as an http 
            // redirect response value.
        };

        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(userIdentity), authProperties);

        //Just redirect to our index after logging in. 
        return Redirect("/dashboard");
    }

    public void OnGet()
    {
    }
}

Dashboard.cshtml

@page
@using System.Security.Claims
@using Microsoft.AspNetCore.Identity
@using ComedyWebsite.Controllers
@model ComedyWebsite.Pages.DashboardModel
@{
}

Hello @User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value

<form asp-controller="Logout" asp-action="Logout" method="post" 
id="logoutForm">
    <button type="submit">Logout</button>
</form>

LogoutController.cs

public class LogoutController : Controller
{
    [HttpPost]
    public async Task<IActionResult> Logout()
    {
        // SomeOtherPage is where we redirect to after signout
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        HttpContext.Response.Cookies.Delete($".AspNetCore.{CookieAuthenticationDefaults.AuthenticationScheme}");
        return Redirect("/");
    }
}


如下图所示,点击注销按钮后,cookie 仍然存在于用户的浏览器中

我尝试了 https://stackoverflow.com/questions/46131517/asp-net-core-identity-2-0-signoutasync 此处给出的解决方案,但这也不起作用。

【问题讨论】:

  • public async Task&lt;IActionResult&gt; Logout()这一行放一个断点,点击Logout时是否命中?

标签: c# asp.net razor asp.net-core asp.net-core-2.2


【解决方案1】:

不完全符合您的要求,但也许这种方法会有所帮助。

我使用的是 Asp.Net Core 2.2,并且在 Account Controller 中有以下 Logout() 方法。我使用身份服务并使用该路径注销而不是 HttpContext。对我来说,这个解决方案有效并删除了登录 cookie —— 至少在我几分钟前检查时是这样。

它与您的代码不同之处在于我使用的是 signInManager 对象而不是 HttpContext 对象,并且此 SignOutAsync() 不带任何参数。

如果你愿意,试试看,看看你会得到什么。请务必在您的 startup.cs ConfigureServices 方法中调用 AddIdentity() 或其变体。

【讨论】:

    【解决方案2】:

    对于您当前的代码,您将MVC ControllerRazor Page 组合在同一个项目中,但您没有为MVC Controller 配置任何路由。

    首先,检查生成的Logout表单的html,确保它生成如下:

    <form method="post" id="logoutForm" action="/Logout/Logout">
        <button type="submit">Logout</button>
    <input name="__RequestVerificationToken" type="hidden" value="xxx"></form>
    

    如果没有,请配置你的 mvc 路由

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
    

    这是一个工作演示TestCookiesAuth

    【讨论】:

      猜你喜欢
      • 2019-01-18
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 2011-03-24
      • 2012-10-01
      • 2012-10-16
      • 2018-03-18
      相关资源
      最近更新 更多