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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
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<string, string> _mapper; static SafeBase64UrlEncoder() { _mapper = new Dictionary<string, string> {{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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
[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
Thanks! It was really helpful for me!