HTTP-sütik az ASP.NET Web API-ban

Ez a témakör azt ismerteti, hogyan küldhet és fogadhat HTTP-cookie-kat a Webes API-ban.

HTTP sütik háttere

Ez a szakasz rövid áttekintést nyújt a cookie-k HTTP-szinten történő implementálásáról. Részletekért tekintse meg az RFC 6265-öt.

A cookie-k olyan adatok, amelyeket a kiszolgáló a HTTP-válaszban küld. Az ügyfél (opcionálisan) tárolja a cookie-t, és a későbbi kérések során visszaadja. Ez lehetővé teszi az ügyfél és a kiszolgáló számára az állapot megosztását. A cookie beállításához a kiszolgáló egy Set-Cookie fejlécet tartalmaz a válaszban. A cookie formátuma egy név-érték pár, opcionális attribútumokkal. Például:

Set-Cookie: session-id=1234567

Íme egy példa attribútumokkal:

Set-Cookie: session-id=1234567; max-age=86400; domain=example.com; path=/;

Ha egy cookie-t vissza szeretne adni a kiszolgálónak, az ügyfél tartalmaz egy cookie-fejlécet a későbbi kérésekben.

Cookie: session-id=1234567

A cookie-k kiszolgálónak való visszaadásának folyamatábraja, amely során az ügyfél egy cookie-fejlécet tartalmaz a későbbi kérésekben.

A HTTP-válaszok több Set-Cookie fejlécet is tartalmazhatnak.

Set-Cookie: session-token=abcdef;
Set-Cookie: session-id=1234567;

Az ügyfél több cookie-t ad vissza egyetlen Cookie-fejléc használatával.

Cookie: session-id=1234567; session-token=abcdef;

A cookie hatókörét és időtartamát a következő attribútumok vezérlik a Set-Cookie fejlécben:

  • Tartomány: Megadja az ügyfélnek, hogy melyik tartomány kapja meg a cookie-t. Ha például a tartomány "example.com", az ügyfél a cookie-t a example.com minden altartományára visszaadja. Ha nincs megadva, a domain a forráskiszolgáló.
  • Elérési út: A cookie-t a tartomány megadott elérési útjára korlátozza. Ha nincs megadva, a rendszer a kérelem URI-jának elérési útját használja.
  • Lejár: Beállítja a cookie lejárati dátumát. Az ügyfél törli a cookie-t, amikor lejár.
  • Maximális életkor: Beállítja a cookie maximális életkorát. Az ügyfél törli a cookie-t, amikor eléri a maximális életkort.

Ha mindkettő ExpiresMax-Age be van állítva, Max-Age elsőbbséget élvez. Ha egyik sincs beállítva, az ügyfél törli a cookie-t, amikor az aktuális munkamenet véget ér. (A "munkamenet" pontos jelentését a felhasználó-ügynök határozza meg.)

Vegye figyelembe azonban, hogy az ügyfelek figyelmen kívül hagyhatják a cookie-kat. Egy felhasználó például adatvédelmi okokból letilthatja a cookie-kat. Az ügyfelek a lejáratuk előtt törölhetik a cookie-kat, vagy korlátozhatják a tárolt cookie-k számát. Adatvédelmi okokból az ügyfelek gyakran elutasítják a "harmadik féltől származó" cookie-kat, ahol a tartomány nem egyezik a forráskiszolgálóval. Röviden: a kiszolgálónak nem szabad arra támaszkodnia, hogy visszakapja az általa megadott cookie-kat.

A webes API-ban található sütik

Ha cookie-t szeretne hozzáadni egy HTTP-válaszhoz, hozzon létre egy CookieHeaderValue-példányt , amely a cookie-t jelöli. Ezután hívja meg a AddCookies bővítménymetódust, amely a System.Net.Http.HttpResponseHeadersExtensions osztályban van definiálva, a cookie hozzáadásához.

A következő kód például hozzáad egy cookie-t egy vezérlőművelethez:

public HttpResponseMessage Get()
{
    var resp = new HttpResponseMessage();

    var cookie = new CookieHeaderValue("session-id", "12345");
    cookie.Expires = DateTimeOffset.Now.AddDays(1);
    cookie.Domain = Request.RequestUri.Host;
    cookie.Path = "/";

    resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });
    return resp;
}

Figyelje meg, hogy az AddCookies egy CookieHeaderValue-példányokból álló tömböt vesz át.

A cookie-k ügyfélkérésből való kinyeréséhez hívja meg a GetCookies metódust :

string sessionId = "";

CookieHeaderValue cookie = Request.Headers.GetCookies("session-id").FirstOrDefault();
if (cookie != null)
{
    sessionId = cookie["session-id"].Value;
}

A CookieHeaderValuecookieState-példányok gyűjteményét tartalmazza. Minden CookieState egy cookie-t jelöl. Az indexelő metódussal a CookieState-t név alapján szerezheti be, ahogy az látható.

Számos böngésző korlátozza, hogy hány cookie-t tárolnak – mind a teljes számot, mind a tartományonkénti számot. Ezért hasznos lehet strukturált adatokat egyetlen cookie-ba helyezni ahelyett, hogy több cookie-t állítanak be.

Megjegyzés:

Az RFC 6265 nem határozza meg a cookie-adatok struktúráját.

A CookieHeaderValue osztály használatával megadhat egy név-érték párok listáját a cookie-adatokhoz. Ezek a név-érték párok URL-kódolású űrlapadatokként vannak kódolva a Set-Cookie fejlécben:

var resp = new HttpResponseMessage();

var nv = new NameValueCollection();
nv["sid"] = "12345";
nv["token"] = "abcdef";
nv["theme"] = "dark blue";
var cookie = new CookieHeaderValue("session", nv); 

resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });

Az előző kód a következő Set-Cookie fejlécet hozza létre:

Set-Cookie: session=sid=12345&token=abcdef&theme=dark+blue;

A CookieState osztály egy indexelő metódust biztosít az alértékek beolvasásához egy cookie-ból a kérelemüzenetben:

string sessionId = "";
string sessionToken = "";
string theme = "";

CookieHeaderValue cookie = Request.Headers.GetCookies("session").FirstOrDefault();
if (cookie != null)
{
    CookieState cookieState = cookie["session"];

    sessionId = cookieState["sid"];
    sessionToken = cookieState["token"];
    theme = cookieState["theme"];
}

Példa: Cookie-k beállítása és lekérése üzenetkezelőben

Az előző példák azt mutatták be, hogyan használhat cookie-kat egy webes API-vezérlőn belül. Egy másik lehetőség az üzenetkezelők használata. Az üzenetkezelőket a rendszer a folyamat korábbi részében hívja meg, mint a vezérlőket. Az üzenetkezelő a kérésből cookie-kat olvashat, mielőtt a kérés elérené a vezérlőt, vagy hozzáadhat cookie-kat a válaszhoz, miután a vezérlő létrehozta a választ.

A cookie-k üzenetkezelőben való beállításának és fogadásának folyamatábraja. Bemutatja, hogyan hívja meg az üzenetkezelőket a folyamat korábban, mint a vezérlők.

Az alábbi kód egy üzenetkezelőt jelenít meg a munkamenet-azonosítók létrehozásához. A munkamenet-azonosítót egy cookie tárolja. A kezelő ellenőrzi a munkamenet-cookie kérését. Ha a kérés nem tartalmazza a cookie-t, a kezelő létrehoz egy új munkamenet-azonosítót. A kezelő mindkét esetben a httpRequestMessage.Properties tulajdonságcsomagban tárolja a munkamenet-azonosítót. Emellett hozzáadja a munkamenet-cookie-t a HTTP-válaszhoz.

Ez az implementáció nem ellenőrzi, hogy az ügyfél munkamenet-azonosítóját ténylegesen a kiszolgáló adta-e ki. Ne használja hitelesítésként! A példa lényege a HTTP-cookie-kezelés megjelenítése.

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;

public class SessionIdHandler : DelegatingHandler
{
    public static string SessionIdToken = "session-id";

    async protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        string sessionId;

        // Try to get the session ID from the request; otherwise create a new ID.
        var cookie = request.Headers.GetCookies(SessionIdToken).FirstOrDefault();
        if (cookie == null)
        {
            sessionId = Guid.NewGuid().ToString();
        }
        else 
        {
            sessionId = cookie[SessionIdToken].Value;
            try
            {
                Guid guid = Guid.Parse(sessionId);
            }
            catch (FormatException)
            {
                // Bad session ID. Create a new one.
                sessionId = Guid.NewGuid().ToString();
            }
        }

        // Store the session ID in the request property bag.
        request.Properties[SessionIdToken] = sessionId;

        // Continue processing the HTTP request.
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

        // Set the session ID as a cookie in the response message.
        response.Headers.AddCookies(new CookieHeaderValue[] {
            new CookieHeaderValue(SessionIdToken, sessionId) 
        });

        return response;
    }
}

A vezérlő lekérheti a munkamenet-azonosítót a HttpRequestMessage.Properties tulajdonságcsomagból.

public HttpResponseMessage Get()
{
    string sessionId = Request.Properties[SessionIdHandler.SessionIdToken] as string;

    return new HttpResponseMessage()
    {
        Content = new StringContent("Your session ID = " + sessionId)
    };
}