From 6784ebbb4a00bec1d2062578b0963ad455b24995 Mon Sep 17 00:00:00 2001 From: Sadika Sumanapala Date: Sat, 21 Jul 2018 14:33:02 +0530 Subject: [PATCH] Use built-in middleware --- Cargo.lock | 3 - cookie-auth/Cargo.toml | 4 - cookie-auth/src/auth.rs | 274 ---------------------------------------- cookie-auth/src/main.rs | 8 +- 4 files changed, 2 insertions(+), 287 deletions(-) delete mode 100644 cookie-auth/src/auth.rs diff --git a/Cargo.lock b/Cargo.lock index d8f67cfe..c6c7bee4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -383,10 +383,7 @@ version = "0.1.0" dependencies = [ "actix 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/cookie-auth/Cargo.toml b/cookie-auth/Cargo.toml index c44474eb..ceda654d 100644 --- a/cookie-auth/Cargo.toml +++ b/cookie-auth/Cargo.toml @@ -7,8 +7,4 @@ workspace = "../" [dependencies] actix = "0.7" actix-web = "0.7" - -cookie = { version="0.10", features=["percent-encode", "secure"] } -futures = "0.1" -time = "0.1" env_logger = "0.5" diff --git a/cookie-auth/src/auth.rs b/cookie-auth/src/auth.rs deleted file mode 100644 index 56ec54e4..00000000 --- a/cookie-auth/src/auth.rs +++ /dev/null @@ -1,274 +0,0 @@ -#![allow(dead_code)] -use std::rc::Rc; - -use cookie::{Cookie, CookieJar, Key}; -use futures::future::{err as FutErr, ok as FutOk, FutureResult}; -use futures::Future; -use time::Duration; - -use actix_web::http::header::{self, HeaderValue}; -use actix_web::middleware::{Middleware, Response, Started}; -use actix_web::{Error, HttpRequest, HttpResponse, Result}; - -/// Trait provides identity service for the request. -pub trait RequestIdentity { - /// Return the claimed identity of the user associated request or - /// ``None`` if no identity can be found associated with the request. - fn identity(&self) -> Option; - - /// Remember identity. - fn remember(&self, identity: String); - - /// This method is used to 'forget' the current identity on subsequent - /// requests. - fn forget(&self); -} - -impl RequestIdentity for HttpRequest { - fn identity(&self) -> Option { - if let Some(id) = self.extensions().get::() { - return id.0.identity().map(|s| s.to_owned()); - } - None - } - - fn remember(&self, identity: String) { - if let Some(id) = self.extensions_mut().get_mut::() { - return id.0.as_mut().remember(identity); - } - } - - fn forget(&self) { - if let Some(id) = self.extensions_mut().get_mut::() { - return id.0.forget(); - } - } -} - -/// An identity -pub trait Identity: 'static { - fn identity(&self) -> Option<&str>; - - fn remember(&mut self, key: String); - - fn forget(&mut self); - - /// Write session to storage backend. - fn write(&mut self, resp: HttpResponse) -> Result; -} - -/// Identity policy definition. -pub trait IdentityPolicy: Sized + 'static { - type Identity: Identity; - type Future: Future; - - /// Parse the session from request and load data from a service identity. - fn from_request(&self, request: &mut HttpRequest) -> Self::Future; -} - -/// Middleware that implements identity service -pub struct IdentityService { - backend: T, -} - -impl IdentityService { - /// Create new identity service with specified backend. - pub fn new(backend: T) -> Self { - IdentityService { backend } - } -} - -struct IdentityBox(Box); - -#[doc(hidden)] -unsafe impl Send for IdentityBox {} -#[doc(hidden)] -unsafe impl Sync for IdentityBox {} - -impl> Middleware for IdentityService { - fn start(&self, req: &HttpRequest) -> Result { - let mut req = req.clone(); - - let fut = self - .backend - .from_request(&mut req) - .then(move |res| match res { - Ok(id) => { - req.extensions_mut().insert(IdentityBox(Box::new(id))); - FutOk(None) - } - Err(err) => FutErr(err), - }); - Ok(Started::Future(Box::new(fut))) - } - - fn response(&self, req: &HttpRequest, resp: HttpResponse) -> Result { - if let Some(mut id) = req.extensions_mut().remove::() { - id.0.write(resp) - } else { - Ok(Response::Done(resp)) - } - } -} - -/// Identity that uses private cookies as identity storage -pub struct CookieIdentity { - changed: bool, - identity: Option, - inner: Rc, -} - -impl Identity for CookieIdentity { - fn identity(&self) -> Option<&str> { - self.identity.as_ref().map(|s| s.as_ref()) - } - - fn remember(&mut self, value: String) { - self.changed = true; - self.identity = Some(value); - } - - fn forget(&mut self) { - self.changed = true; - self.identity = None; - } - - fn write(&mut self, mut resp: HttpResponse) -> Result { - if self.changed { - let _ = self.inner.set_cookie(&mut resp, self.identity.take()); - } - Ok(Response::Done(resp)) - } -} - -struct CookieIdentityInner { - key: Key, - name: String, - path: String, - domain: Option, - secure: bool, - max_age: Option, -} - -impl CookieIdentityInner { - fn new(key: &[u8]) -> CookieIdentityInner { - CookieIdentityInner { - key: Key::from_master(key), - name: "actix-identity".to_owned(), - path: "/".to_owned(), - domain: None, - secure: true, - max_age: None, - } - } - - fn set_cookie(&self, resp: &mut HttpResponse, id: Option) -> Result<()> { - let some = id.is_some(); - { - let id = id.unwrap_or_else(|| String::new()); - let mut cookie = Cookie::new(self.name.clone(), id); - cookie.set_path(self.path.clone()); - cookie.set_secure(self.secure); - cookie.set_http_only(true); - - if let Some(ref domain) = self.domain { - cookie.set_domain(domain.clone()); - } - - if let Some(max_age) = self.max_age { - cookie.set_max_age(max_age); - } - - let mut jar = CookieJar::new(); - if some { - jar.private(&self.key).add(cookie); - } else { - jar.add_original(cookie.clone()); - jar.private(&self.key).remove(cookie); - } - - for cookie in jar.delta() { - let val = HeaderValue::from_str(&cookie.to_string())?; - resp.headers_mut().append(header::SET_COOKIE, val); - } - } - - Ok(()) - } - - fn load(&self, req: &mut HttpRequest) -> Option { - if let Ok(cookies) = req.cookies() { - for cookie in cookies.iter() { - if cookie.name() == self.name { - let mut jar = CookieJar::new(); - jar.add_original(cookie.clone()); - - let cookie_opt = jar.private(&self.key).get(&self.name); - if let Some(cookie) = cookie_opt { - return Some(cookie.value().into()); - } - } - } - } - None - } -} - -/// Use cookies for request identity. -pub struct CookieIdentityPolicy(Rc); - -impl CookieIdentityPolicy { - /// Construct new `CookieIdentityPolicy` instance. - /// - /// Panics if key length is less than 32 bytes. - pub fn new(key: &[u8]) -> CookieIdentityPolicy { - CookieIdentityPolicy(Rc::new(CookieIdentityInner::new(key))) - } - - /// Sets the `path` field in the session cookie being built. - pub fn path>(mut self, value: S) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().path = value.into(); - self - } - - /// Sets the `name` field in the session cookie being built. - pub fn name>(mut self, value: S) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().name = value.into(); - self - } - - /// Sets the `domain` field in the session cookie being built. - pub fn domain>(mut self, value: S) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().domain = Some(value.into()); - self - } - - /// Sets the `secure` field in the session cookie being built. - /// - /// If the `secure` field is set, a cookie will only be transmitted when the - /// connection is secure - i.e. `https` - pub fn secure(mut self, value: bool) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().secure = value; - self - } - - /// Sets the `max-age` field in the session cookie being built. - pub fn max_age(mut self, value: Duration) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().max_age = Some(value); - self - } -} - -impl IdentityPolicy for CookieIdentityPolicy { - type Identity = CookieIdentity; - type Future = FutureResult; - - fn from_request(&self, req: &mut HttpRequest) -> Self::Future { - let identity = self.0.load(req); - FutOk(CookieIdentity { - identity, - changed: false, - inner: Rc::clone(&self.0), - }) - } -} diff --git a/cookie-auth/src/main.rs b/cookie-auth/src/main.rs index f7a0c09c..a7444793 100644 --- a/cookie-auth/src/main.rs +++ b/cookie-auth/src/main.rs @@ -1,14 +1,10 @@ extern crate actix; extern crate actix_web; -extern crate cookie; extern crate env_logger; -extern crate futures; -extern crate time; use actix_web::{middleware, server, App, HttpRequest, HttpResponse}; - -mod auth; -use auth::{CookieIdentityPolicy, IdentityService, RequestIdentity}; +use actix_web::middleware::identity::RequestIdentity; +use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; fn index(req: &HttpRequest) -> String { format!("Hello {}", req.identity().unwrap_or("Anonymous".to_owned()))