Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely store Unicode characters in cookies?

I'm using cookies to display some data in a search page but my cookies are garbling the values when using Unicode characters. For example when I store Inglês, I'm getting Inglês when I read it back.

This is how I save my cookie:

public void SalvaValue(string sessionKey, string sessionValue)
{
    Response.Cookies.Add(new HttpCookie(sessionKey));

    var httpCookie = Response.Cookies[sessionKey];

    if (httpCookie != null) httpCookie.Value = sessionValue;
    if (httpCookie != null) httpCookie.Expires = DateTime.Now.AddDays(14);
}

This is how I retrieve it:

if (Request.Cookies["BuscaTipo"] != null)
{
    tipoBusca = Request.Cookies["BuscaTipo"].Value.ToString();

     var cookie = new HttpCookie("BuscaTipo") { Expires = DateTime.Now.AddDays(-1) };
     Response.Cookies.Add(cookie);
}

When I debug the site, it shows the right value in code when setting it, but after I perform a request with jQuery, the value comes up with the wrong characters.

How can I safely store Unicode characters in cookies?

like image 335
Ariel Avatar asked Feb 13 '15 19:02

Ariel


People also ask

Can a cookie contain special characters?

According to the standards of the Internet Engineering Task Force (IETF), the institution responsible for documenting standards used on the Internet, cookies cannot have special characters in their composition, including non-ASCII characters.

What characters are allowed in a cookie?

A cookie definition begins with a name-value pair. A <cookie-name> can contain any US-ASCII characters except for: the control character, space, or a tab. It also must not contain separator characters like the following: ( ) < > @ , ; : \ " / [ ] ?

Is used to store Unicode characters?

Data types nchar, nvarchar, and long nvarchar are used to store Unicode data. They behave similarly to char, varchar, and long varchar character types respectively, except that each character in a Unicode type typically uses 16 bits.

What encoding type is used for cookies?

Simply enter your data then push the encode button. To encode binaries (like images, documents, etc.)


1 Answers

See How to store other languages (unicode) in cookies and get it back again, Unicode Cookie Value, How to send non-English unicode string using HTTP header? and Allowed characters in cookies for an explanation why you need to encode cookie values.

In short: Unicode characters in headers (in which cookies are sent) are supported by most browsers, but not all. Some browsers interpret the Unicode bytes as ASCII, resulting in Mojibake.

jQuery also seems to play a role according to some of the linked questions, but I cannot reproduce that.

Therefore to safely store Unicode characters (or rather any non-ASCII or control characters) across all browsers, you need to encode the characters. This can be implemented through, for example, base64 and percent-encoding.

An implementation of the latter, slightly adapted from Cookies and Unicode characters:

public static class CookieExtensions
{
    public static string DecodedValue(this HttpCookie cookie)
    {
        if (cookie == null)
        {
            throw new ArgumentNullException("cookie");
        }
        return HttpUtility.UrlDecode(cookie.Value);
    }

    public static void SetEncodedValue(this HttpCookie cookie, string value)
    {
        if (cookie == null)
        {
            throw new ArgumentNullException("cookie");
        }
        cookie.Value = HttpUtility.UrlEncode(value);
    }

    public static string DecodedValues(this HttpCookie cookie, string name)
    {
        if (cookie == null)
        {
            throw new ArgumentNullException("cookie");
        }
        return HttpUtility.UrlDecode(cookie.Values[name]);
    }

    public static void SetEncodedValues(this HttpCookie cookie, string name, string value)
    {
        if (cookie == null)
        {
            throw new ArgumentNullException("cookie");
        }
        cookie.Values[name] = HttpUtility.UrlEncode(value);
    }

    public static string DecodedValues(this HttpCookie cookie, int index)
    {
        if (cookie == null)
        {
            throw new ArgumentNullException("cookie");
        }
        return HttpUtility.UrlDecode(cookie.Values[index]);
    }
}

Usage:

if (Request.Cookies["TestCookieValue"] != null)
{
    ViewBag.CookieValue = Request.Cookies["TestCookieValue"].DecodedValue();
}

if (Request.Cookies["TestCookieValues"] != null)
{
    ViewBag.CookieValues = Request.Cookies["TestCookieValues"].DecodedValues("foo");
    ViewBag.CookieValuesIndexed = Request.Cookies["TestCookieValues"].DecodedValues(0);
}

var cookieWithValue = new HttpCookie("TestCookieValue");
cookieWithValue.Expires = DateTime.Now.AddHours(1);
cookieWithValue.SetEncodedValue("Inglês");
Response.SetCookie(cookieWithValue);

var cookieWithValues = new HttpCookie("TestCookieValues");
cookieWithValues.Expires = DateTime.Now.AddHours(1);
cookieWithValues.SetEncodedValues("foo", "Inglês");
Response.SetCookie(cookieWithValues);

Please note HttpUtility.UrlDecode() is dangerous, use AntiXSS to prevent Cross-site Scripting and SQL injection from the cookie values, which can be arbitrarily set by the client.

You may also perhaps reconsider storing Unicode values in cookies. You can easily identify the language otherwise, for example through the code en-US or its database index if applicable.

like image 167
CodeCaster Avatar answered Nov 28 '22 00:11

CodeCaster