微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 为什么最终用户必须注销两次?

我试图让IdentityServer4在新的.NET Core 2.1应用程序中运行(它在.NET Core 2.0应用程序中完美运行).我尝试过以下方法

1)下载此项目,即IdentityServer4应用程序:https://github.com/ghstahl/IdentityServer4-Asp.Net-2.1-Identity-Examples/tree/e0aeeff7e078aa082c8e16029dd2c220acc77d7b

2)使用Identity Server4应用程序下载此项目,即MVC应用程序:https://github.com/IdentityServer/IdentityServer4.Samples/tree/dev/Quickstarts/6_AspNetIdentity/src/MvcClient.

3)将两个项目添加到同一解决方案中. MVC项目使用IdentityServer项目进行身份验证;授权等

我不得不做出以下改变:

1)更改为IdentityServer应用程序中包含的Startup(AddIdentityServer现在接受参数):

services.AddIdentityServer(options =>
{
    options.UserInteraction.LoginUrl = "/Identity/Account/Login";
    options.UserInteraction.logoutUrl = "/Identity/Account/logout";
})

2)配置IdentityServer应用程序以侦听端口5000并在身份服务器上禁用SSL.

除了注销工具外,一切都按预期开箱即用.当我在MVC应用程序中单击注销时;在MVC应用程序中调用以下代码

public async Task logout() 
{ 
    await HttpContext.SignOutAsync("Cookies"); 
    await HttpContext.SignOutAsync("oidc"); 
}

然后,用户重定向到IdentityServer应用程序中的logout.cshtml.但是,他们必须再次单击注销(在IdentityServer应用程序上)才能实际注销,即他们在MVC应用程序中单击注销(第二点),然后在IdentityServer中注销(第一点).

为什么最终用户必须注销两次?

解决方法

在帐户/注销页面中,它位于您的脚手架ASP.NET核心标识代码中的Areas / Identity / Account / logout.cshtml.cs下,有一个OnGet处理程序,如下所示:
public void OnGet() { }

因为这是使用ASP.NET Core Razor Pages,所以这一切都是渲染相应的logout.cshtml页面.在您的示例中,当您在MVC应用程序中点击logout时,它会清除自己的cookie,然后将您转到IS4应用程序(特别是OnGet).因为这个OnGet处理程序是空的,所以它并没有真正做任何事情,它肯定不会让你退出IS4应用程序.

如果你看一下logout.cshtml.cs里面的OnPost处理程序,你会发现它看起来像这样:

public async Task<IActionResult> OnPost(string returnUrl = null)
{
    await _signInManager.SignOutAsync();
    // ...
}

对SignOutAsync的这种调用完全符合它的建议:它会让你退出IS4本身.但是,在当前工作流程中,不会调用此OnPost处理程序.当我在MVC应用程序中使用logout时,会间接调用OnGet处理程序,正如我已经提到的那样.

现在,如果你看一下Quickstart.UI项目中IS4注销的控制器/动作实现,你会看到它本质上将GET请求传递给POST请求.这是代码,删除了注释:

[HttpGet]
public async Task<IActionResult> logout(string logoutId)
{
    var vm = await BuildlogoutviewmodelAsync(logoutId);

    if (vm.ShowlogoutPrompt == false)
        return await logout(vm);

    return View(vm);
}

当注销时,有一个设置控制是否应首先提示用户确认他们是否要注销.这主要是代码所处理的 – 如果不需要提示,它会直接将其传递给POST请求处理程序.这是POST的代码片段:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> logout(logoutInputModel model)
{
    var vm = await BuildLoggedOutviewmodelAsync(model.logoutId);

    if (User?.Identity.IsAuthenticated == true)
    {
        await HttpContext.SignOutAsync();

        // ...
    }

    // ...

    return View("LoggedOut",vm);
}

这里的重要一行是对HttpContext.SignOutAsync的调用 – 这最终会删除IS4用来保持登录的cookie.一旦删除,你就会退出IS4.最终,这是您当前实施中缺少的内容.

在最简单的级别,您可以通过更新OnGet来解决您的问题,如下所示:

public async Task<IActionResult> OnGet()
{
    if (User?.Identity.IsAuthenticated == true)
    {
        await _signInManager.SignOutAsync();          
        return RedirectToPage(); // A redirect ensures that the cookies has gone.
    }

    return Page();
}

不支持我上面详述的ShowlogoutPrompt选项,只是为了让这个答案更短一些.除此之外,它只是使用_signInManager来执行注销,因为您处于ASP.NET核心身份世界中.

我鼓励你探索Quickstart.UI实现的完整源代码,以支持ShowlogoutPrompt,returnUrl等 – 如果不写书,我不可能在这里做.

原文地址:https://www.jb51.cc/csharp/100149.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐