Skip to content
代码片段 群组 项目
未验证 提交 863ef43d 编辑于 作者: Javier Calvarro Nelson's avatar Javier Calvarro Nelson 提交者: GitHub
浏览文件

[Blazor] Get rid of the custom QueryStringHelper implementation (#42532)

* Reuse existing query string infrastructure
上级 c9fabaef
No related branches found
No related tags found
无相关合并请求
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="Sdk.props" Sdk="Yarn.MSBuild" Condition=" '$(DotNetBuildFromSource)' != 'true'" />
......@@ -9,6 +9,8 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsTrimmable>true</IsTrimmable>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>DISABLE_NULLABLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
......@@ -22,6 +24,7 @@
<ItemGroup>
<Compile Include="$(SharedSourceRoot)LinkerFlags.cs" LinkBase="Shared" />
<Compile Include="$(SharedSourceRoot)QueryStringEnumerable.cs" LinkBase="Shared" />
</ItemGroup>
<PropertyGroup>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication;
internal static class QueryStringHelper
{
public static string GetParameter(string queryString, string key)
{
if (string.IsNullOrEmpty(queryString) || queryString == "?")
{
return null;
}
var scanIndex = 0;
if (queryString[0] == '?')
{
scanIndex = 1;
}
var textLength = queryString.Length;
var equalIndex = queryString.IndexOf('=');
if (equalIndex == -1)
{
equalIndex = textLength;
}
while (scanIndex < textLength)
{
var ampersandIndex = queryString.IndexOf('&', scanIndex);
if (ampersandIndex == -1)
{
ampersandIndex = textLength;
}
if (equalIndex < ampersandIndex)
{
while (scanIndex != equalIndex && char.IsWhiteSpace(queryString[scanIndex]))
{
++scanIndex;
}
var name = queryString[scanIndex..equalIndex];
var value = queryString.Substring(equalIndex + 1, ampersandIndex - equalIndex - 1);
var processedName = Uri.UnescapeDataString(name.Replace('+', ' '));
if (string.Equals(processedName, key, StringComparison.OrdinalIgnoreCase))
{
return Uri.UnescapeDataString(value.Replace('+', ' '));
}
equalIndex = queryString.IndexOf('=', ampersandIndex);
if (equalIndex == -1)
{
equalIndex = textLength;
}
}
else
{
if (ampersandIndex > scanIndex)
{
var value = queryString[scanIndex..ampersandIndex];
if (string.Equals(value, key, StringComparison.OrdinalIgnoreCase))
{
return string.Empty;
}
}
}
scanIndex = ampersandIndex + 1;
}
return null;
}
}
......@@ -4,6 +4,7 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Internal;
using static Microsoft.AspNetCore.Internal.LinkerFlags;
namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication;
......@@ -329,7 +330,7 @@ public class RemoteAuthenticatorViewCore<[DynamicallyAccessedMembers(JsonSeriali
return state.ReturnUrl;
}
var fromQuery = QueryStringHelper.GetParameter(new Uri(Navigation.Uri).Query, "returnUrl");
var fromQuery = GetParameterFromQueryString("returnUrl");
if (!string.IsNullOrWhiteSpace(fromQuery) && !fromQuery.StartsWith(Navigation.BaseUri, StringComparison.Ordinal))
{
// This is an extra check to prevent open redirects.
......@@ -337,6 +338,29 @@ public class RemoteAuthenticatorViewCore<[DynamicallyAccessedMembers(JsonSeriali
}
return fromQuery ?? defaultReturnUrl ?? Navigation.BaseUri;
}
private string GetParameterFromQueryString(ReadOnlySpan<char> parameterName)
{
var url = Navigation.Uri;
ReadOnlyMemory<char> query = default;
var queryStartPos = url.IndexOf('?');
if (queryStartPos >= 0)
{
var queryEndPos = url.IndexOf('#', queryStartPos);
query = url.AsMemory(queryStartPos..(queryEndPos < 0 ? url.Length : queryEndPos));
}
foreach (var parameter in new QueryStringEnumerable(query))
{
var decodedName = parameter.DecodeName().Span;
if (MemoryExtensions.Equals(parameterName, decodedName, StringComparison.OrdinalIgnoreCase))
{
return new string(parameter.DecodeValue().Span);
}
}
return null;
}
private void NavigateToReturnUrl(string returnUrl) => Navigation.NavigateTo(returnUrl, new NavigationOptions { ForceLoad = false, ReplaceHistoryEntry = true });
......
......@@ -30,7 +30,11 @@ internal
/// Constructs an instance of <see cref="QueryStringEnumerable"/>.
/// </summary>
/// <param name="queryString">The query string.</param>
#if DISABLE_NULLABLE
public QueryStringEnumerable(string queryString)
#else
public QueryStringEnumerable(string? queryString)
#endif
: this(queryString.AsMemory())
{
}
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册