lilydocs
HTTP APIWebSocketConsumer
Güvenlik3 dk okuma

CSRF

Browser sinyalleri, session binding ve token kontrolüyle CSRF korumasını kurun.

CSRF koruması varsayılan olarak kapalıdır. Önce uygulamanızın session modelini, ardından hangi CSRF profilini kullanacağını seçin.

Profil seçimi#

Profil Kontrol Uygulamanın sağlaması gereken
cross_origin() Origin ve Fetch Metadata Browser sinyalleri
signed_double_submit(secret, binding) Session’a bağlı signed token Secret ve binding
defense_in_depth(secret, binding) Origin ve signed token Secret ve binding
synchronizer(secret, binding, store) Server-side token CsrfTokenStore implementation’ı
synchronizer_defense_in_depth(...) Origin ve server-side token Binding, secret ve store

cross_origin() profilinde hem Origin hem Sec-Fetch-Site yoksa unsafe istek kabul edilebilir. Token doğrulaması isteyen uygulamada token içeren bir profil seçin.

Session binding ve kurulum#

Session middleware’ın doğruladığı session ID’yi CsrfSessionId::new(...) ile request-local state’e koyun. Aşağıdaki composition parçasında secret ve middleware uygulamaya aittir:

Rust
let policy = CsrfPolicy::defense_in_depth(
    CsrfSecret::new(application_secret)?,
    CsrfRequestLocalBinding::new(),
)
.trust_origins(["https://app.example.com"])
.token_header("x-csrf-token")
.token_ttl(std::time::Duration::from_secs(3600));

let builder = AppBuilder::new("127.0.0.1:8080")
    .session_middleware::<ApplicationSessionMiddleware>()
    .csrf(policy);

CsrfSessionCookieBinding::new(name) alternatifinde cookie değeri binding olarak alınır. Bu yol session store’a gidip oturumun geçerliliğini kendiliğinden denetlemez.

Global veya route kapsamı#

.csrf(policy) unsafe isteklerde global koruma uygular; exact bypass(method, path) istisnaları seçilebilir. .csrf_route_scoped(policy) yalnız #[guard(CsrfGuard)] action’larını korur. Session yayımlayan route guard’ı varsa CsrfGuard’dan önce gelmelidir.

İki mod birlikte kullanılamaz. Policy olmadan CsrfGuard, global modla birlikte CsrfGuard veya hiçbir CsrfGuard kullanmayan route-scoped kurulum build hatasıdır.

Token endpoint’i#

Önce policy ve session binding kurulmuş olmalıdır. serde_json = "1" ekleyin. Bu controller token’ı JSON olarak verir:

csrf.rs
use std::sync::Arc;
use lilyrs::http_api::{
    controller, Controller, ControllerInitError, ControllerTrait, CsrfService,
    Extensions, HttpApiError, Request, Response, Service,
};

#[derive(Controller)]
#[base_path("/security")]
struct SecurityController;

#[lilyrs::http_api::async_trait::async_trait]
impl ControllerTrait for SecurityController {
    async fn new(_: Arc<Extensions>) -> Result<Self, ControllerInitError> { Ok(Self) }
}

#[controller]
impl SecurityController {
    #[get("/csrf")]
    async fn csrf_token(
        &self, Service(csrf): Service<CsrfService>,
        request: &mut Request, response: &mut Response,
    ) -> Result<(), HttpApiError> {
        let token = csrf.issue(request, response).await.map_err(|_| {
            HttpApiError::ServiceUnavailable("CSRF token unavailable".into())
        })?;
        response.try_insert_header("content-type", "application/json")
            .map_err(|_| HttpApiError::ResponseEncodingError("header rejected".into()))?;
        response.try_insert_header("cache-control", "no-store")
            .map_err(|_| HttpApiError::ResponseEncodingError("header rejected".into()))?;
        let body = serde_json::to_vec(&serde_json::json!({ "token": token.as_str() }))
            .map_err(|_| HttpApiError::ResponseEncodingError("JSON failed".into()))?;
        response.set_body_vec(body)?;
        Ok(())
    }
}

Manual response, signed profilin yazdığı Set-Cookie’yi korur. Browser token’ı JSON’dan alıp unsafe istekte x-csrf-token header’ıyla gönderir. HTTP-only cookie JavaScript’ten okunmaz. Cross-origin akışta CORS credentials ve browser credentials ayarlarını da tamamlayın.

Rotation ve store#

rotate, clear, previous_verification_key, cookie_policy, token_ttl ve URL-encoded form için allow_form_field seçenekleri vardır. Signed profilde session ID değişince yeni binding’e token verin. Synchronizer profilde eski binding’in state’ini ID değişmeden temizleyin.

CsrfTokenStore load-or-insert, rotate ve revoke işlemlerinin atomiklik sözleşmesini uygulamalıdır. Birden fazla instance varsa yalnız process belleğinde tutulan map yeterli ortak store olmaz.

Bu sayfanın kaynakları v0.1.0

Anlatım, incelenen framework commit’ine dayanır.

HIZLI BAŞLANGIÇ
Dokümantasyon
Kaynak kod