Kaynağa Gözat

Adding sessions

clement 1 yıl önce
ebeveyn
işleme
df9ac6cdfd
4 değiştirilmiş dosya ile 306 ekleme ve 9 silme
  1. 242 2
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 13 2
      src/main.rs
  4. 50 5
      src/users/routes.rs

+ 242 - 2
Cargo.lock

@@ -30,7 +30,7 @@ dependencies = [
  "actix-service",
  "actix-utils",
  "ahash",
- "base64",
+ "base64 0.21.7",
  "bitflags 2.5.0",
  "brotli",
  "bytes",
@@ -119,6 +119,24 @@ dependencies = [
  "pin-project-lite",
 ]
 
+[[package]]
+name = "actix-session"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b671404ec72194d8af58c2bdaf51e3c477a0595056bd5010148405870dda8df2"
+dependencies = [
+ "actix-service",
+ "actix-utils",
+ "actix-web",
+ "anyhow",
+ "derive_more",
+ "rand",
+ "redis",
+ "serde",
+ "serde_json",
+ "tracing",
+]
+
 [[package]]
 name = "actix-utils"
 version = "3.0.1"
@@ -196,6 +214,41 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
+[[package]]
+name = "aead"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+dependencies = [
+ "crypto-common",
+ "generic-array",
+]
+
+[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "aes-gcm"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
+dependencies = [
+ "aead",
+ "aes",
+ "cipher",
+ "ctr",
+ "ghash",
+ "subtle",
+]
+
 [[package]]
 name = "ahash"
 version = "0.8.11"
@@ -248,6 +301,18 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "anyhow"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
+[[package]]
+name = "arc-swap"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
+
 [[package]]
 name = "async-trait"
 version = "0.1.80"
@@ -280,6 +345,12 @@ dependencies = [
  "rustc-demangle",
 ]
 
+[[package]]
+name = "base64"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
+
 [[package]]
 name = "base64"
 version = "0.21.7"
@@ -290,6 +361,7 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 name = "bim-ng"
 version = "0.1.0"
 dependencies = [
+ "actix-session",
  "actix-web",
  "config",
  "deadpool",
@@ -426,6 +498,30 @@ dependencies = [
  "phf_codegen",
 ]
 
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "combine"
+version = "4.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+ "tokio-util",
+]
+
 [[package]]
 name = "config"
 version = "0.14.0"
@@ -487,7 +583,14 @@ version = "0.16.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
 dependencies = [
+ "aes-gcm",
+ "base64 0.20.0",
+ "hkdf",
+ "hmac",
  "percent-encoding",
+ "rand",
+ "sha2",
+ "subtle",
  "time",
  "version_check",
 ]
@@ -564,9 +667,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
 dependencies = [
  "generic-array",
+ "rand_core",
  "typenum",
 ]
 
+[[package]]
+name = "ctr"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
+dependencies = [
+ "cipher",
+]
+
 [[package]]
 name = "deadpool"
 version = "0.12.1"
@@ -620,6 +733,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
 dependencies = [
  "block-buffer",
  "crypto-common",
+ "subtle",
 ]
 
 [[package]]
@@ -812,6 +926,16 @@ dependencies = [
  "wasi",
 ]
 
+[[package]]
+name = "ghash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
+dependencies = [
+ "opaque-debug",
+ "polyval",
+]
+
 [[package]]
 name = "gimli"
 version = "0.28.1"
@@ -879,6 +1003,24 @@ version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
 [[package]]
 name = "http"
 version = "0.2.12"
@@ -970,6 +1112,15 @@ dependencies = [
  "hashbrown 0.14.5",
 ]
 
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "itoa"
 version = "1.0.11"
@@ -1215,6 +1366,12 @@ version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
+[[package]]
+name = "opaque-debug"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+
 [[package]]
 name = "openssl"
 version = "0.10.64"
@@ -1402,6 +1559,26 @@ dependencies = [
  "siphasher",
 ]
 
+[[package]]
+name = "pin-project"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.61",
+]
+
 [[package]]
 name = "pin-project-lite"
 version = "0.2.14"
@@ -1420,6 +1597,18 @@ version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
 
+[[package]]
+name = "polyval"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash",
+]
+
 [[package]]
 name = "powerfmt"
 version = "0.2.0"
@@ -1480,6 +1669,30 @@ dependencies = [
  "getrandom",
 ]
 
+[[package]]
+name = "redis"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c580d9cbbe1d1b479e8d67cf9daf6a62c957e6846048408b80b43ac3f6af84cd"
+dependencies = [
+ "arc-swap",
+ "async-trait",
+ "bytes",
+ "combine",
+ "futures",
+ "futures-util",
+ "itoa",
+ "native-tls",
+ "percent-encoding",
+ "pin-project-lite",
+ "ryu",
+ "tokio",
+ "tokio-native-tls",
+ "tokio-retry",
+ "tokio-util",
+ "url",
+]
+
 [[package]]
 name = "redox_syscall"
 version = "0.5.1"
@@ -1524,7 +1737,7 @@ version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
 dependencies = [
- "base64",
+ "base64 0.21.7",
  "bitflags 2.5.0",
  "serde",
  "serde_derive",
@@ -1751,6 +1964,12 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "subtle"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
 [[package]]
 name = "syn"
 version = "1.0.109"
@@ -1921,6 +2140,17 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "tokio-retry"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f"
+dependencies = [
+ "pin-project",
+ "rand",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-stream"
 version = "0.1.15"
@@ -2088,6 +2318,16 @@ version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
 
+[[package]]
+name = "universal-hash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+dependencies = [
+ "crypto-common",
+ "subtle",
+]
+
 [[package]]
 name = "url"
 version = "2.5.0"

+ 1 - 0
Cargo.toml

@@ -7,6 +7,7 @@ edition = "2021"
 
 [dependencies]
 actix-web = "4"
+actix-session = { version = "0.9.0", features = ["redis-rs-tls-session"] }
 ldap3 = "0.11.3"
 tera = "1.0"
 serde = "1.0.199"

+ 13 - 2
src/main.rs

@@ -1,4 +1,5 @@
-use actix_web::{web, App, HttpServer};
+use actix_web::{cookie::{Key, SameSite}, web, App, HttpServer};
+use actix_session::{storage::RedisSessionStore, SessionMiddleware};
 use config::Config;
 use ldap::{pool::LdapConfig, LdapWrapper};
 use std::env;
@@ -13,7 +14,10 @@ async fn main() -> std::io::Result<()> {
     .build()
     .unwrap();
 
-    let config = LdapConfig{
+    let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379").await.unwrap();
+    let signing_key = Key::generate();
+
+    let config = LdapConfig {
         hostname: settings.get("hostname").unwrap(),
         port: settings.get("port").unwrap(),
         basedn: settings.get("basedn").unwrap(),
@@ -25,9 +29,16 @@ async fn main() -> std::io::Result<()> {
 
     HttpServer::new(move ||  {
         App::new()
+        .wrap(
+            SessionMiddleware::builder(redis_store.clone(), signing_key.clone())
+            .cookie_same_site(SameSite::Strict)
+            .build()
+        )
         .app_data(web::Data::new(ldap_wrapper.clone()))
         .service(users::routes::index)
         .service(users::routes::auth)
+        .service(users::routes::home)
+        .service(users::routes::signout)
     })
     .bind(("127.0.0.1", 8080))?
     .run()

+ 50 - 5
src/users/routes.rs

@@ -1,4 +1,5 @@
-use actix_web::{get, http::StatusCode, post, web, HttpResponse, Responder, http::header};
+use actix_session::Session;
+use actix_web::{ get, http::{header, StatusCode}, post, web, HttpResponse, Responder};
 use ldap::LdapWrapper;
 use serde::Deserialize;
 use tera::Tera;
@@ -10,6 +11,20 @@ struct FormLoginData {
     password: String,
 }
 
+fn validate_session(session: &Session) -> bool {
+    let user_id: Option<String> = session
+    .get("user_id")
+    .unwrap_or(None);
+
+    match user_id {
+        Some(_id) => {
+            session.renew();
+            return true;
+        }
+        None => return false
+    }
+}
+
 async fn get_template(template_name: String) -> String {
     let tera = Tera::new("templates/*.html")
     .expect("Failed to parse template files");
@@ -19,16 +34,21 @@ async fn get_template(template_name: String) -> String {
 }
 
 #[get("/")]
-async fn index() -> impl Responder {
+async fn index(session: Session) -> impl Responder {
+    if validate_session(&session) {
+        return HttpResponse::Ok()
+        .status(StatusCode::FOUND)
+        .append_header((header::LOCATION, "/home"))
+        .finish();
+    }
+
     let body = get_template("signin.html".to_string()).await;
     HttpResponse::Ok().content_type("text/html")
     .body(body)
 }
 
 #[post("/auth")]
-async fn auth(ldap_wrapper: web::Data<LdapWrapper>, form: web::Form<FormLoginData>) -> impl Responder {
-    let body = get_template("home.html".to_string()).await;
-
+async fn auth(ldap_wrapper: web::Data<LdapWrapper>, form: web::Form<FormLoginData>, session: Session) -> impl Responder {
     let user_authed = controller::login(&ldap_wrapper, &form.id, &form.password)
     .await;
 
@@ -39,6 +59,31 @@ async fn auth(ldap_wrapper: web::Data<LdapWrapper>, form: web::Form<FormLoginDat
         .finish();
     }
 
+    session.insert("user_id", &form.id).unwrap();
+    HttpResponse::Ok()
+    .status(StatusCode::FOUND)
+    .append_header((header::LOCATION, "/home"))
+    .finish()
+}
+
+#[get("/home")]
+async fn home(session: Session) -> impl Responder {
+    if !validate_session(&session) {
+        return HttpResponse::Ok()
+        .status(StatusCode::FOUND)
+        .append_header((header::LOCATION, "/"))
+        .finish();
+    }
+    let body = get_template("home.html".to_string()).await;
     HttpResponse::Ok().content_type("text/html")
     .body(body)
+}
+
+#[get("/signout")]
+async fn signout(session: Session) -> impl Responder {
+    session.purge();
+    HttpResponse::Ok()
+    .status(StatusCode::FOUND)
+    .append_header((header::LOCATION, "/"))
+    .finish()
 }