ASP.NET Web API クッキーのエンコードについて
stackoverflow - WebAPI encoding cookie values
ASP.NET MVC ではクッキーの取得・設定時に、値のエンコード/デコードは行われませんが、
ASP.NET Web API の場合は、URL エンコード/デコードが行われます。
ASP.NET Web API
ASP.NET Web API におけるクッキーの取得・設定の例。
キー「abcd」に「"!()_-*.aA0 ?#$%&|@\\/[]{}<>+=^~\"'`;:,あ"」を設定しています。
using System; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web.Http; namespace CookieTry.Controllers { public class MyApiController : ApiController { [Route("apitest")] public HttpResponseMessage Get() { var requestCookie = Request.Headers.GetCookies("abcd").FirstOrDefault()?["abcd"]?.Value; Debug.WriteLine(requestCookie); string abcd = "!()_-*.aA0 ?#$%&|@\\/[]{}<>+=^~\"'`;:,あ"; var cookie = new CookieHeaderValue("abcd", abcd); cookie.Path = "/"; cookie.Expires = DateTime.Now.AddDays(1); var response = Request.CreateResponse(HttpStatusCode.OK); response.Headers.AddCookies(new CookieHeaderValue[] { cookie }); return response; } } }
この時、HTTP Response のヘッダーのクッキーの部分は、
Set-Cookie: abcd=!()_-*.aA0+%3f%23%24%25%26%7c%40%5c%2f%5b%5d%7b%7d%3c%3e%2b%3d%5e%7e%22%27%60%3b%3a%2c%e3%81%82; path=/
とエンコードされて書き出します。
また、リクエストにあるクッキーを Debug.WriteLine(requestCookie); で出力していますが、この時の値はデコードされたものとなります。
response.Headers.AddCookies(..) は、System.Net.Http.Formatting.dll にある拡張メソッド HttpResponseHeadersExtensions.cs です。
※
cookie.Domain = Request.RequestUri.Host;
でホストを指定した場合、デバッグ時等で URL が localhost:xxxx の環境ではレスポンスにて「domain=localhost;」になるので注意(リクエスト時にクッキーが送信されない)。
ASP.NET MVC
同じ例で、ASP.NET MVC の場合。
using System.Diagnostics; using System.Web; using System.Web.Mvc; namespace CookieTry.Controllers { public class MyMvcController : Controller { public ActionResult Index() { string requestCookie = Request.Cookies["abcd"]?.Value; Debug.WriteLine(requestCookie); var cookie = new HttpCookie("abcd", "!()_-*.aA0 ?#$%&|@\\/[]{}<>+=^~\"'`;:,あ"); cookie.Path = "/"; Response.Cookies.Add(cookie); return View(); } } }
この時、HTTP Response のヘッダーのクッキーの部分は
Set-Cookie: abcd=!()_-*.aA0 ?#$%&|@\/[]{}<>+=^~"'`;:,あ; path=/
と、エンコードされません。
Request.Cookies["abcd"]?.Valueで取得するリクエストのクッキーは、デコードされません。
補足
ASP.NET Web API の「response.Headers.AddCookies(new CookieHeaderValue[] { cookie });」のメソッドでは丁寧にコメントがかかれています。
ここでは Cookie に関するオブジェクトの説明と、構造化の仕組みについてあります。
構造化…ASP.NET Web API では一つのキーに対して複数の値を仕込むことができます。(詳細:HTTP Cookies in ASP.NET Web API)
// 概要: // 応答に Cookie を追加します。各 [Set-Cookie] ヘッダーは、1 つの System.Net.Http.Headers.CookieHeaderValue // インスタンスとして表現されます。System.Net.Http.Headers.CookieHeaderValue には、ドメインやパスなどの Cookie // 情報だけでなく、1 つ以上の System.Net.Http.Headers.CookieState インスタンスも含まれます。各 System.Net.Http.Headers.CookieState // インスタンスには、Cookie の名前、およびその名前と関連付けられているすべての Cookie の状態が含まれます。状態の形式は System.Collections.Specialized.NameValueCollection // で、ワイヤーは HTML フォームの URL エンコード データとしてエンコードされています。このような表現により、複数の関連した "Cookie" // を同じ [Cookie] ヘッダー内で伝達すると同時に、各 Cookie で状態を分離することが可能になります。[Cookie] ヘッダーの例を以下に示します。この例には、それぞれ // [state1] および [state2] という名前が含まれる 2 つの System.Net.Http.Headers.CookieState // が存在します。さらに、各 Cookie の状態には 2 つの名前/値のペア (name1/value1 と name2/value2) および (name3/value3 // と name4/value4) が含まれています。<code> Set-Cookie: state1:name1=value1&name2=value2; // state2:name3=value3&name4=value4; domain=domain1; path=path1; </code> // // パラメーター: // headers: // 応答のヘッダー // // cookies: // 応答に追加する Cookie の値。 public static void AddCookies(this HttpResponseHeaders headers, IEnumerable<CookieHeaderValue> cookies);
Web API の内部で行われる URL エンコードは、System.Net.WebUtility.UrlEncode とほぼ同様とみていいと思います。
Web API の URL エンコードまわりのソース:
「NETFX_CORE」(Portable Class Library かどうか)で、WebUtilityを使うかどうか分岐があります。PCL でない場合、UriQueryUtility.cs に描かれている実装でエンコード/デコードされます。
.NET Framework 4.6 の WebUtility.cs
WebUtility.cs の方と UriQueryUtility.cs にある実装ですが、若干コードの違いが。一つ、大文字と小文字の差異がありました。