我正在将一个针对net472
的项目移植到netstandard
。我坚持的最后一个System.Web
依赖是HttpServerUtility.UrlTokenEncode(Byte[])
。
我发现Microsoft.AspNetCore.WebUtilities
,其中包含Base64UrlTextEncoder
和WebEncoders
,但这些不能与UrlTokenEncode
/ Decode
互换,因为它追加/期望=
padding characters的数量,例如:
var data = Encoding.UTF8.GetBytes("SO");
Convert.ToBase64String(data); // U08=
HttpServerUtility.UrlTokenEncode(data); // U081 - this is what's expected and
// the only thing UrlTokenDecode can handle
Base64UrlTextEncoder.Encode(data); // U08
WebEncoders.Base64UrlEncode(data); // U08
据我所知,没有其他差异(我使用随机字符串运行测试),但它也引入了一些其他依赖项(Microsoft.Net.Http.Headers和Microsoft.Extensions.Primitives),我不知道真的需要在那个项目中。
是否有任何nuget包装与直接替换?我想自己实现这个,如果没有。
我的KISS,解决方案,适用于netstandard1.6
:
public static class Utils
{
private static readonly Regex InvalidBase64UrlTokens = new Regex(
@"[^=a-z0-9]",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
public static string Base64UrlTokenEncode(byte[] data)
{
var padding = 0;
var base64String = Convert.ToBase64String(data);
return InvalidBase64UrlTokens.Replace(base64String, m => {
switch (m.Value)
{
case "+": return "-";
case "=":
padding++;
return "";
default: return "_";
}
}) + padding;
}
}
通过以下nunit测试:
[TestFixture]
public class Base64UrlTokenEncodingTests
{
private static IEnumerable<TestCaseData> CompareAgainstSystemWebImplementationCases()
{
var random = new Random(42);
for (var i = 0; i < 100; i++)
{
var bytes = new byte[i + 1];
random.NextBytes(bytes);
var name = Convert.ToBase64String(bytes);
var systemWeb = System.Web.HttpServerUtility.UrlTokenEncode(bytes);
yield return new TestCaseData(bytes).SetName(name).Returns(systemWeb);
}
}
[TestCaseSource(nameof(CompareAgainstSystemWebImplementationCases))]
public string CompareAgainstSystemWebImplementation(byte[] data) =>
Utils.Base64UrlTokenEncode(data);
}