Skip to main content

rustbasic_core/middleware/
security_headers.rs

1/* ---------------------------------------------------------
2 * 📑 LABEL: SECURITY HEADERS
3 * Menambahkan header keamanan standar industri.
4 * --------------------------------------------------------- */
5
6use axum::{
7    body::Body,
8    http::{Request, header},
9    middleware::Next,
10    response::Response,
11};
12
13pub async fn security_headers_middleware(
14    req: Request<Body>,
15    next: Next,
16) -> Response {
17    let mut response = next.run(req).await;
18    
19    let headers = response.headers_mut();
20    
21    // 1. Mencegah Clickjacking
22    headers.insert(header::X_FRAME_OPTIONS, "DENY".parse().unwrap());
23    
24    // 2. Mencegah MIME Sniffing
25    headers.insert(header::X_CONTENT_TYPE_OPTIONS, "nosniff".parse().unwrap());
26    
27    // 3. XSS Protection (untuk browser lama)
28    headers.insert(header::X_XSS_PROTECTION, "1; mode=block".parse().unwrap());
29    
30    // 4. Content Security Policy (Lengkap)
31    let cfg = crate::Config::load();
32    let csp = if cfg.app_debug {
33        let port = cfg.vite_port;
34        let host = &cfg.app_host;
35        let extra_hosts = if host != "0.0.0.0" && host != "127.0.0.1" && host != "localhost" && !host.is_empty() {
36            format!("http://{}:{} ws://{}:{} ", host, port, host, port)
37        } else {
38            "".to_string()
39        };
40
41        format!(
42            "default-src 'self'; \
43             script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost:{} http://127.0.0.1:{} {}https:; \
44             style-src 'self' 'unsafe-inline' http://localhost:{} http://127.0.0.1:{} {}https:; \
45             font-src 'self' https: data:; \
46             img-src 'self' data: https:; \
47             connect-src 'self' ws://localhost:{} ws://127.0.0.1:{} http://localhost:{} http://127.0.0.1:{} {}https:;",
48            port, port, extra_hosts,
49            port, port, extra_hosts,
50            port, port, port, port, extra_hosts
51        )
52    } else {
53        "default-src 'self'; \
54         script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; \
55         style-src 'self' 'unsafe-inline' https:; \
56         font-src 'self' https: data:; \
57         img-src 'self' data: https:; \
58         connect-src 'self' https:;".to_string()
59    };
60    headers.insert(header::CONTENT_SECURITY_POLICY, csp.parse().unwrap());
61    
62    response
63}