如何将 returnUrl 传递到 Blazor Server 应用程序中的登录页面?

Ran*_*age 10 c# identity server blazor

我有一个简单的 Blazor 服务器应用程序,身份使用个人身份验证。我从 VS 2019 标准dotnet new模板创建了该应用程序。

在应用程序的某些部分,我想将用户定向到登录页面,同时传递一个returnUrl参数。我尝试了以下代码变体来传递此参数(counter是我要返回的页面):

NavigationManager.NavigateTo("Identity/Account/Login?returnUrl=counter", forceLoad: true);
Run Code Online (Sandbox Code Playgroud)
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='/counter'", forceLoad: true);
Run Code Online (Sandbox Code Playgroud)
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='./counter'", forceLoad: true);
Run Code Online (Sandbox Code Playgroud)
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='~/counter'", forceLoad: true);
Run Code Online (Sandbox Code Playgroud)

但是,对于所有这些,我收到一条错误消息,指出“URI 不是本地的”。错误信息是:

“InvalidOperationException:提供的 URL 不是本地的。具有绝对路径的 URL 如果没有主机/权限部分,则被认为是本地的。使用虚拟路径 ('~/') 的 URL 也是本地的。”

在这种情况下,有人可以建议正确格式化 returnUrl 参数吗?有关更多背景信息,我正在关注@iambacon(感谢 Colin!)在他关于重定向到 Blazor 应用程序登录页面的博客文章中的建议。这是一篇很棒的文章,完成了我想要的部分内容:当用户未通过身份验证时重定向到登录。我只想添加在身份验证完成后返回该 URL 的额外功能。

Isa*_*aac 12

“URI 不是本地的”。

为了解决这个...

请执行下列操作:

  1. 在 Pages 文件夹中创建一个名为 RedirectToLogin 的组件,代码如下:

RedirectToLogin.razor

@inject NavigationManager NavigationManager

@code{
  [Parameter]
  public string ReturnUrl {get; set;}
  protected override  void OnInitialized()
  {
        ReturnUrl = "~/" + ReturnUrl;
        NavigationManager.NavigateTo($"Identity/Account/Login?returnUrl={ReturnUrl}", 
           forceLoad:true);
  }
}
Run Code Online (Sandbox Code Playgroud)

打开 App.razor 并将以下代码添加到 AuthorizeRouteView.NotAuthorized

<NotAuthorized>
@{
    var returnUrl = 
    NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
    <RedirectToLogin ReturnUrl="@returnUrl"/>
    
 }
</NotAuthorized>
Run Code Online (Sandbox Code Playgroud)

同样在 App 组件的顶部注入 NavigationManager,如下所示:

@inject NavigationManager NavigationManager
Run Code Online (Sandbox Code Playgroud)

为了测试这一点,在 Fetchdata(或 Counter,如果你喜欢)组件页面的顶部为 Authorize 属性添加 @attribute 指令,如下所示:@attribute [Authorize]当未经身份验证的用户尝试访问 Fetchdata 页面时,AuthorizeRouteView.NotAuthorized 委托属性是执行,并呈现 RedirectToLogin 组件,其参数属性设置为当前 url。

更新

以下添加是在您的应用程序中添加登录和注销按钮...

  1. 在 Shared 文件夹中创建一个名为 LoginDisplay.razor 的组件,并在其中添加以下代码:
     <AuthorizeView>
      <Authorized>
        <a href="Identity/Account/Manage">Hello, 
        @context.User.Identity.Name!</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log 
        out</button>
        </form>
      </Authorized>
         <NotAuthorized>
            <a href="Identity/Account/Register">Register</a>
            <a href="Identity/Account/Login">Log in</a>
         </NotAuthorized>
      </AuthorizeView>
Run Code Online (Sandbox Code Playgroud)

在 MainLayout 组件中添加 LoginDisplay 元素,如下所示:

<div class="top-row px-4 auth">
    <LoginDisplay />
    <a href="https://docs.microsoft.com/aspnet/" 
         target="_blank">About</a>
</div>
Run Code Online (Sandbox Code Playgroud)

运行您的应用程序并测试登录和注销按钮...

  • 感谢您的建议。我曾计划过类似的设计。我实现了你的所有代码,但现在遇到了同样的错误。在 Login.cshtml.cs 代码中的断点处,我可以看到 returnUrl 设置为“fetchData”。我不明白为什么它认为这是一条非本地路径。 (2认同)
  • 更新:我发现如果单击应用程序中的 fetchData 链接,则会收到“URI 不是本地”错误。但是,如果我将 url 编辑为 /fetchData 路径,则会收到不同的错误。断点位于 RedirectToLogin 组件内部的 .NavigateTo 方法处。错误消息是“Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:授权失败。抛出异常:Microsoft.AspNetCore.Components.Server.dll 中的'Microsoft.AspNetCore.Components.NavigationException'”,没有更多详细信息。 (2认同)
  • 抱歉,我很困惑。你是说该网址不是本地的,但你也说它可以这样做。如果 returnUrl(“fetchData”)不是本地的,为什么您的解决方案可以工作? (2认同)
  • “输入登录凭据后”这是您未能提供的关键信息... (2认同)