How to do safe base64 url encoding in ASP .NET, I came into a problem of url encoding in IIS 7 where it does not like “+”, “/” in the Url. Basically a Url that looks like of like this
http://fake.abc/TIRlcEq0umjO6uJqtqvnkUGntUzv19rK+8mcvPK5qL1bwEZtEUqTlc3iF/TomuXU746Il5IF2iN9SeYuYDqt6SQzfdrv+Ltug2KZteKlYawc=
I know you may say what is this??? Its actually some kind of encrypted data that is in base64, but since IIS 7 does not like “+” or “/” even if its url encoded.
So I made a Utility class string extension method that just simply replaces the characters with “-” and “_”
Here is the code so maybe someday it would help you out also.
public static class SafeBase64UrlEncoder
{
private const string Plus = "+";
private const string Minus = "-";
private const string Slash = "/";
private const string Underscore = "_";
private const string EqualSign = "=";
private const string Pipe = "|";
private static readonly IDictionary _mapper;
static SafeBase64UrlEncoder()
{
_mapper = new Dictionary {{Plus, Minus}, {Slash, Underscore}, {EqualSign, Pipe}};
}
public static string EncodeBase64Url(this string base64Str)
{
if (string.IsNullOrEmpty(base64Str))
return base64Str;
foreach (var pair in _mapper)
{
base64Str = base64Str.Replace(pair.Key, pair.Value);
}
return base64Str;
}
public static string DecodeBase64Url(this string safe64Url)
{
if (string.IsNullOrEmpty(safe64Url))
return safe64Url;
foreach (var pair in _mapper)
{
safe64Url = safe64Url.Replace(pair.Value, pair.Key);
}
return safe64Url;
}
}
And always there should be a test for it.
[TestFixture]
public class SafeBase64UrlTests
{
[Test]
public void Encode64Url_Should_Replace_Plus_With_Minus()
{
var str = "+".EncodeBase64Url();
Assert.That(str.Equals("-"),Is.True);
}
[Test]
public void Encode64Url_Should_Replace_ThreePlus_With_ThreeMinus()
{
var str = "+++".EncodeBase64Url();
Assert.That(str.Equals("---"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_Minus_With_Plus()
{
var str = "-".DecodeBase64Url();
Assert.That(str.Equals("+"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_ThreeMinus_With_ThreePlus()
{
var str = "---".DecodeBase64Url();
Assert.That(str.Equals("+++"), Is.True);
}
[Test]
public void Encode64Url_Should_Replace_Slash_With_Underscore()
{
var str = "/".EncodeBase64Url();
Assert.That(str.Equals("_"), Is.True);
}
[Test]
public void Encode64Url_Should_Replace_ThreeSlash_With_ThreeUnderscore()
{
var str = "///".EncodeBase64Url();
Assert.That(str.Equals("___"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_Underscore_With_Slash()
{
var str = "_".DecodeBase64Url();
Assert.That(str.Equals("/"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_ThreeUnderscore_With_ThreeSlash()
{
var str = "___".DecodeBase64Url();
Assert.That(str.Equals("///"), Is.True);
}
[Test]
public void Encode64Url_Should_Replace_Equal_With_Pipe()
{
var str = "=".EncodeBase64Url();
Assert.That(str.Equals("|"), Is.True);
}
[Test]
public void Encode64Url_Should_Replace_ThreeEqual_With_ThreePipe()
{
var str = "===".EncodeBase64Url();
Assert.That(str.Equals("|||"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_Pipe_With_Equal()
{
var str = "|".DecodeBase64Url();
Assert.That(str.Equals("="), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_ThreePipe_With_ThreeEqual()
{
var str = "|||".DecodeBase64Url();
Assert.That(str.Equals("==="), Is.True);
}
[Test]
public void Encode64Url_Should_Replace_EqualSlashPlus_With_MinusUnderscorePipe()
{
var str = "=+/".EncodeBase64Url();
Assert.That(str.Equals("|-_"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_MinusUnderscorePipe_With_EqualSlashPlus()
{
var str = "|-_".DecodeBase64Url();
Assert.That(str.Equals("=+/"), Is.True);
}
[Test]
public void Encode64Url_Should_Replace_EqualSlashPlus_With_MinusUnderscorePipe_With_Alpha_Numeric_Characters()
{
var str = "1A=2b+3C/4d".EncodeBase64Url();
Assert.That(str.Equals("1A|2b-3C_4d"), Is.True);
}
[Test]
public void Decode64Url_Should_Replace_MinusUnderscorePipe_With_EqualSlashPlus_With_Alpha_Numeric_Characters()
{
var str = "1a|2B-3c_4D".DecodeBase64Url();
Assert.That(str.Equals("1a=2B+3c/4D"), Is.True);
}
[Test]
public void Encode64Url_Should_Return_Same_String_When_Empty()
{
var str = string.Empty.EncodeBase64Url();
Assert.That(string.IsNullOrEmpty(str), Is.True);
}
[Test]
public void Decode64Url_Should_Return_Same_String_When_Empty()
{
var str = string.Empty.DecodeBase64Url();
Assert.That(string.IsNullOrEmpty(str), Is.True);
}
[Test]
public void Encode64Url_Should_Return_Same_String_When_Null()
{
string str = null;
str = str.EncodeBase64Url();
Assert.That(string.IsNullOrEmpty(str), Is.True);
}
[Test]
public void Decode64Url_Should_Return_Same_String_When_Null()
{
string str = null;
str = str.DecodeBase64Url();
Assert.That(string.IsNullOrEmpty(str), Is.True);
}
}
There are other ways of fixing this and one can read them at
http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-containing.aspx
http://bentaylor.org/dasBlog-Patch-Add-Choice-Of-Dash-For-Post-Title-URL-Spaces.aspx
View Comments (1)
Thanks! It was really helpful for me!