如何将 returnUrl 传递到 Blazor Server 应用程序中的登录页面?
Posted
技术标签:
【中文标题】如何将 returnUrl 传递到 Blazor Server 应用程序中的登录页面?【英文标题】:How do I pass returnUrl to Login page in Blazor Server application? 【发布时间】:2020-04-30 20:07:18 【问题描述】:我有一个简单的 Blazor 服务器应用程序,其身份使用个人身份验证。我从 VS 2019 标准 dotnet new
模板创建了应用程序。
在应用程序的某些部分,我想将用户引导到登录页面,同时传递returnUrl
参数。我尝试了以下代码变体来传递此参数(counter 是我要返回的页面):
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl=counter", forceLoad: true);
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='/counter'", forceLoad: true);
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='./counter'", forceLoad: true);
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='~/counter'", forceLoad: true);
但是,通过所有这些,我收到一条错误消息,指出“URI 不是本地的”。错误信息是:
"InvalidOperationException: 提供的 URL 不是本地的。带有 如果绝对路径没有 主机/权限部分。使用虚拟路径 ('~/') 的 URL 也是本地的。”
在这种情况下,谁能建议 returnUrl 参数的正确格式?有关更多背景信息,我正在遵循 @iambacon 的建议(感谢 Colin!),在他的 blog post 中关于重定向到 Blazor 应用程序的登录页面。这是一篇很棒的文章,完成了我想要的部分内容:当用户未通过身份验证时重定向到登录。我只想添加额外的功能,即在身份验证完成后返回该 URL。
【问题讨论】:
错误是在 NavigateTo() 上还是在您再次离开登录页面时出现? 【参考方案1】:“URI 不是本地的”。
要解决这个问题...
执行以下操作:
-
在 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);
打开 App.razor 并将以下代码添加到 AuthorizeRouteView.NotAuthorized
<NotAuthorized>
@
var returnUrl =
NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
<RedirectToLogin ReturnUrl="@returnUrl"/>
</NotAuthorized>
同样在 App 组件的顶部注入 NavigationManager,如下所示:
@inject NavigationManager NavigationManager
为了测试这一点,在 Fetchdata(或 Counter,如果你喜欢)组件页面的顶部添加 Authorize 属性的 @attribute 指令,如下所示:@attribute [Authorize]
当未经身份验证的用户尝试访问 Fetchdata 页面时,执行 AuthorizeRouteView.NotAuthorized 委托属性,并渲染 RedirectToLogin 组件,并将其参数属性设置为当前 url。
更新
以下添加是为你的App添加登录和注销按钮...
-
在 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>
在 MainLayout 组件中添加 LoginDisplay 元素,如下所示:
<div class="top-row px-4 auth">
<LoginDisplay />
<a href="https://docs.microsoft.com/aspnet/"
target="_blank">About</a>
</div>
运行您的应用并测试登录和注销按钮...
【讨论】:
感谢您的建议。我曾计划过类似的设计。我实现了你所有的代码,现在我得到了同样的错误。在 Login.cshtml.cs 代码的断点处,我可以看到 returnUrl 设置为“fetchData”。我不明白为什么它认为这是一条非本地路径。 更新:我发现如果我单击应用程序中的 fetchData 链接,我会收到“URI 不是本地”错误。但是,如果我改为将 url 编辑为 /fetchData 路径,则会出现不同的错误。断点位于 RedirectToLogin 组件内部的 .NavigateTo 方法处。错误消息是“Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:授权失败。抛出的异常:Microsoft.AspNetCore.Components.Server.dll 中的'Microsoft.AspNetCore.Components.NavigationException'”没有更多详细信息。 对不起,我很困惑。你是说 url 不是本地的,但你也说它可以这样做。如果 returnUrl ("fetchData") 不是本地的,为什么您的解决方案会起作用? 复制:dotnet new blazor --auth 个人。将@attribute [Authorize] 添加到/fetchdata 页面,并将您推荐的代码添加到App.razor。我没有对默认的 VS 2019 模板进行其他更改。运行app,注册账号,进入首页,点击FetchData,登录,会看到“URL is not local error”。 "输入登录凭据后" 这是您未能提供的关键信息...以上是关于如何将 returnUrl 传递到 Blazor Server 应用程序中的登录页面?的主要内容,如果未能解决你的问题,请参考以下文章