w00*_*977 7 c# asp.net-core identityserver4 asp.net-core-identity
我试图让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";
})
Run Code Online (Sandbox Code Playgroud)
2)配置IdentityServer应用程序以侦听端口5000并在身份服务器上禁用SSL.
除了注销工具外,一切都按预期开箱即用.当我在MVC应用程序中单击注销时; 在MVC应用程序中调用以下代码:
public async Task Logout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}
Run Code Online (Sandbox Code Playgroud)
然后,用户将重定向到IdentityServer应用程序中的Logout.cshtml.但是,他们必须再次单击注销(在IdentityServer应用程序上)才能实际注销,即他们在MVC应用程序中单击注销(第二点),然后在IdentityServer中注销(第一点).
为什么最终用户必须注销两次?
在位于脚手架 ASP.NET Core Identity 代码Account/Logout下方的页面中Areas/Identity/Account/Logout.cshtml.cs,有一个OnGet如下所示的处理程序:
public void OnGet() { }
Run Code Online (Sandbox Code Playgroud)
因为这是使用 ASP.NET Core Razor Pages,所以它所做的只是呈现相应的Logout.cshtml页面。在您的示例中,当您点击LogoutMVC 应用程序时,它会清除自己的 cookie,然后将您传递到 IS4 应用程序(OnGet特别是 )。因为这个OnGet处理程序是空的,所以它实际上并没有做任何事情,而且它肯定不会让您退出 IS4 应用程序。
如果您查看OnPost内部的处理程序Logout.cshtml.cs,您会发现它看起来像这样:
public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync();
// ...
}
Run Code Online (Sandbox Code Playgroud)
这个调用SignOutAsync完全按照它的建议进行:它使您退出 IS4 本身。但是,在您当前的工作流程中,OnPost不会调用此处理程序。正如我已经提到的,当您在 MVC 应用程序中使用时,处理OnGet程序会被间接调用。Logout
现在,如果您查看Quickstart.UI项目中 IS4 logout 的控制器/操作实现,您会发现本质上它是将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);
}
Run Code Online (Sandbox Code Playgroud)
注销时,有一个设置可以控制是否首先提示用户确认是否要注销。这主要是这段代码所关心的——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);
}
Run Code Online (Sandbox Code Playgroud)
这里重要的一行是调用HttpContext.SignOutAsync- 这最终会删除 IS4 用于保持您登录状态的 cookie。一旦删除了该 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();
}
Run Code Online (Sandbox Code Playgroud)
这不支持ShowLogoutPrompt我上面详细介绍的选项,只是为了让这个答案更短一些。除此之外,它只是用来_signInManager执行注销,因为您处于 ASP.NET Core Identity 世界中。
我鼓励您探索Quickstart.UI实现的完整源代码,以支持ShowLogoutPrompt、returnUrl等 - 如果不写一本书,我不可能在这里做到这一点。
| 归档时间: |
|
| 查看次数: |
1289 次 |
| 最近记录: |