代码之家  ›  专栏  ›  技术社区  ›  w0051977

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

  •  7
  • w0051977  · 技术社区  · 6 年前

    我正在尝试让IdentityServer4在一个新的.NET Core 2.1应用程序中工作(它在一个.netcore2.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应用程序中包含的启动(addentityserver现在接受一个参数):

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

    2) 将identity server应用程序配置为在端口5000上侦听,并在identity server上禁用SSL。

    除了注销设备外,一切都按预期的开箱即用。当我在MVC应用程序中单击“注销”时;在MVC应用程序中调用以下代码:

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

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

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

    3 回复  |  直到 5 年前
        1
  •  3
  •   Kirk Larkin    6 年前

    Account/Logout 佩奇,住在 Areas/Identity/Account/Logout.cshtml.cs 在您的框架式ASP.NET核心标识代码中,有一个 OnGet 处理程序如下所示:

    public void OnGet() { }
    

    因为这使用的是ASP.NET核心剃须刀页面,所以所做的只是呈现相应的 Logout.cshtml 第页。在你的例子中,当你击中 Logout 在MVC应用程序中,它清除自己的cookies,然后将您传递到IS4应用程序( 翁盖特 ,具体来说)。因为这个 翁盖特 handler是空的,它实际上什么也没做,它肯定不会让你退出IS4应用程序。

    如果你看看 OnPost 处理器内部 Logout.cshtml.cs ,你会看到它看起来像这样:

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

    这个电话 SignOutAsync 做它所暗示的:它标志着你退出IS4本身。但是,在您当前的工作流中 岗位 未调用处理程序。这个 翁盖特 当您使用 注销 在MVC应用程序中,正如我已经提到的。

    现在,如果您在 Quickstart.UI 项目,您将看到它基本上通过了 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);
    }
    

    注销时,有一个设置控制是否应首先提示用户确认是否要注销。这就是代码要处理的主要内容-它直接传递给 岗位 如果不需要提示,则请求处理程序。下面是 岗位 :

    [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。最后,这是当前实现中缺少的。

    在最简单的级别上,您可以通过更新 翁盖特 像这样:

    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核心标识世界中,请执行注销操作。

    我鼓励您从 快速启动.UI 实施以支持 显示注销提示 , returnUrl 等等-我不可能不写本书就这么做。

        2
  •  1
  •   adem caglin    6 年前

    简单的注销功能如下:

            private readonly SignInManager<IdentityUser> _signInManager;
            private readonly ILogger<LogoutModel> _logger;
            private readonly IIdentityServerInteractionService _interaction;
            public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger,
                IIdentityServerInteractionService interaction)
            {
                _signInManager = signInManager;
                _logger = logger;
                _interaction = interaction;
            }
    
            public async Task<IActionResult> OnGet(string logoutId)
            {
                return await OnPost(logoutId);
            }
    
            public async Task<IActionResult> OnPost(string logoutId)
            {
                await _signInManager.SignOutAsync();
                _logger.LogInformation("User logged out.");
                var r = await _interaction.GetLogoutContextAsync(logoutId);
                if (r.PostLogoutRedirectUri == null)
                {
                    return Redirect("/");
                }
                return Redirect(r.PostLogoutRedirectUri);
            }
    
        3
  •  0
  •   Kroksys    5 年前

    我也有同样的问题 我解决了 我决定把我的答案放在这里让其他人看看。

    解决方案: IdentityServer4中的快速启动项目逻辑已经存在,可以根据用户需要进行配置。

    1. 打开SolutionName/Quickstart/Account/AccountOptions.cs
    2. 显示注销提示
    3. 自动定向信号后 真实的

    Example

    我希望这会有帮助,祝你好运。