Çerez (Cookie), bir web sunucusu tarafından kullanıcının web tarayıcısına gönderilen ve tarayıcı tarafından kullanıcının bilgisayarında depolanan küçük bir veri parçasıdır. Tarayıcı, aynı sunucuya yapılan sonraki isteklerle birlikte bu çerezi geri gönderir. Çerezler, web uygulamalarında çeşitli amaçlar için kullanılır:
* Oturum Yönetimi: Kullanıcı giriş bilgilerini, alışveriş sepeti öğelerini veya diğer durum bilgilerini tutarak kullanıcının oturumunu sürdürmek.
* Kişiselleştirme: Kullanıcı tercihlerini (örneğin, dil ayarları, tema seçimi) hatırlayarak web sitesi deneyimini kişiselleştirmek.
* Takip: Kullanıcı davranışlarını izlemek, site içi gezinmeyi analiz etmek veya hedeflenmiş reklamlar sunmak (genellikle üçüncü taraf çerezleri aracılığıyla).
Çerezlerin Temel Özellikleri:
* Ad (Name) ve Değer (Value): Çerezin depoladığı anahtar-değer çifti.
* Domain (Alan Adı): Çerezin hangi alan adlarına gönderileceğini belirler. Genellikle çerezi ayarlayan sunucunun alan adıdır.
* Path (Yol): Çerezin hangi URL yolları için geçerli olduğunu belirtir. Sadece belirtilen yol veya alt yolları için tarayıcı çerezi gönderir.
* Expires (Sona Erme Tarihi) / Max-Age (Maksimum Yaş): Çerezin kalıcılığını belirler. `Expires` belirli bir tarih ve saati, `Max-Age` ise çerezin ayarlandığı andan itibaren ne kadar süre geçerli olacağını saniye cinsinden belirtir. Bu özellikler yoksa, çerez tarayıcı oturumu sona erdiğinde silinir (oturum çerezi).
* Secure (Güvenli): Bu özellik ayarlanırsa, çerez sadece HTTPS (şifreli) bağlantılar üzerinden gönderilir. Hassas veriler için hayati öneme sahiptir.
* HttpOnly (Sadece HTTP): Bu özellik ayarlanırsa, çereze istemci tarafındaki JavaScript kodları aracılığıyla erişilemez. Bu, Cross-Site Scripting (XSS) saldırılarıyla çerez hırsızlığını önlemeye yardımcı olur.
* SameSite (Aynı Site): Çerezin çapraz site istekleriyle birlikte gönderilip gönderilmeyeceğini kontrol eder. `Lax`, `Strict` ve `None` gibi değerler alabilir. Cross-Site Request Forgery (CSRF) saldırılarına karşı koruma sağlar.
Çerezlerin Çalışma Prensibi:
1. Sunucudan Tarayıcıya: Web sunucusu, bir HTTP yanıtında `Set-Cookie` başlığı aracılığıyla tarayıcıya bir veya daha fazla çerez gönderir.
2. Tarayıcıdan Sunucuya: Tarayıcı, daha sonra aynı sunucuya (veya uygun alan adı/yol eşleşmelerine sahip sunuculara) yapılan sonraki HTTP isteklerinde `Cookie` başlığı aracılığıyla depoladığı çerezleri geri gönderir.
Güvenlik Hususları:
* XSS (Cross-Site Scripting): Bir saldırganın web sitesine kötü niyetli betik enjekte etmesi durumunda çerezler çalınabilir. `HttpOnly` bayrağı bu riski azaltır.
* CSRF (Cross-Site Request Forgery): Saldırgan, kullanıcının bilgisi olmadan, kullanıcının kimlik doğrulanmış oturum çerezlerini kullanarak kötü niyetli istekler göndermesini sağlayabilir. `SameSite` bayrağı ve CSRF belirteçleri bu tür saldırılara karşı koruma sağlar.
* Güvenli Olmayan İletim: `Secure` bayrağı olmadan gönderilen çerezler, ağ üzerindeki saldırganlar tarafından kolayca okunabilir veya değiştirilebilir.
Rust'ta Çerezler: Rust web çerçeveleri (Axum, Actix-Web, Warp vb.) genellikle çerezleri kolayca yönetmek için yerleşik veya entegre kütüphaneler sağlar. Bu kütüphaneler, `Set-Cookie` ve `Cookie` başlıklarının ayrıştırılması ve oluşturulması gibi düşük seviyeli detayları soyutlayarak geliştiricilere yüksek seviyeli bir API sunar. `axum-extra` gibi eklentiler, `cookie` kütüphanesinin Rust projelerinde rahatça kullanılmasına olanak tanır.
Example Code
```rust
// Cargo.toml
// [dependencies]
// axum = "0.7"
// tokio = { version = "1", features = ["full"] }
// axum-extra = { version = "0.9", features = ["cookies"] }
// time = { version = "0.3", features = ["macros", "formatting"] } # macros for time::Duration::minutes
use axum::{
routing::get,
extract::CookieJar,
response::IntoResponse,
Router,
};
use axum_extra::extract::cookie::{Cookie, SameSite};
use http::StatusCode;
// Handler to set a session cookie
// Session cookies expire when the browser is closed (no Max-Age/Expires specified).
async fn set_session_cookie_handler(jar: CookieJar) -> (CookieJar, String) {
let cookie = Cookie::new("my_session_cookie", "session_value_123");
let updated_jar = jar.add(cookie);
(updated_jar, "Session cookie 'my_session_cookie' has been set!".to_string())
}
// Handler to set a persistent cookie with various attributes
async fn set_persistent_cookie_handler(jar: CookieJar) -> (CookieJar, String) {
// A persistent cookie expires after a specified duration.
let cookie = Cookie::build(("my_persistent_cookie", "persistent_value_456"))
.path("/") // Makes the cookie available across the entire domain
.max_age(time::Duration::minutes(5)) // Expires in 5 minutes
.secure(true) // Only send over HTTPS
.http_only(true) // Not accessible via client-side JavaScript
.same_site(SameSite::Lax) // Lax SameSite policy to mitigate CSRF
.finish();
let updated_jar = jar.add(cookie);
(updated_jar, "Persistent cookie 'my_persistent_cookie' (5 min, secure, httponly, samesite=Lax) has been set!".to_string())
}
// Handler to read cookies from the incoming request
async fn get_cookies_handler(jar: CookieJar) -> String {
let mut response_text = String::new();
response_text.push_str("--- Received Cookies ---\n");
if let Some(session_cookie) = jar.get("my_session_cookie") {
response_text.push_str(&format!("Session cookie 'my_session_cookie': {}", session_cookie.value()));
response_text.push_str("\n");
} else {
response_text.push_str("Session cookie 'my_session_cookie' not found.");
response_text.push_str("\n");
}
if let Some(persistent_cookie) = jar.get("my_persistent_cookie") {
response_text.push_str(&format!("Persistent cookie 'my_persistent_cookie': {}", persistent_cookie.value()));
response_text.push_str("\n");
} else {
response_text.push_str("Persistent cookie 'my_persistent_cookie' not found.");
response_text.push_str("\n");
}
response_text.push_str("---------------------\n");
response_text
}
// Handler to delete a cookie
async fn delete_cookie_handler(jar: CookieJar) -> (CookieJar, String) {
// To delete a cookie, you typically send a new Set-Cookie header with the same name,
// an expiry date in the past, and matching domain/path attributes.
// `jar.remove` simplifies this by creating such a cookie for you.
let updated_jar = jar.remove(Cookie::named("my_persistent_cookie"));
(updated_jar, "Persistent cookie 'my_persistent_cookie' has been deleted!".to_string())
}
#[tokio::main]
async fn main() {
// Build our application routes
let app = Router::new()
.route("/", get(|| async {
"Welcome to the Axum Cookie Demo!\n\n"
.to_string() +
"Try the following routes:\n"
"- /set-session-cookie: Sets a temporary session cookie\n"
"- /set-persistent-cookie: Sets a persistent cookie (expires in 5 min) with secure attributes\n"
"- /get-cookies: Reads and displays any cookies sent by your browser\n"
"- /delete-persistent-cookie: Deletes the persistent cookie"
}))
.route("/set-session-cookie", get(set_session_cookie_handler))
.route("/set-persistent-cookie", get(set_persistent_cookie_handler))
.route("/get-cookies", get(get_cookies_handler))
.route("/delete-persistent-cookie", get(delete_cookie_handler));
// Bind the server to an address and start listening for requests
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("Server running on http://127.0.0.1:3000");
axum::serve(listener, app).await.unwrap();
}
```








Cookie