Add Verified FromRequest types for optional middlewares

This commit is contained in:
asonix 2019-09-13 18:27:04 -05:00
parent fef18d96db
commit f4139af189
4 changed files with 49 additions and 12 deletions

View file

@ -33,7 +33,7 @@ impl SignatureVerify for MyVerify {
} }
} }
fn index() -> &'static str { fn index(_: (DigestVerified, SignatureVerified)) -> &'static str {
"Eyyyyup" "Eyyyyup"
} }
@ -44,8 +44,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
HttpServer::new(move || { HttpServer::new(move || {
App::new() App::new()
.wrap(VerifyDigest::new(Sha256::new())) .wrap(VerifyDigest::new(Sha256::new()).optional())
.wrap(VerifySignature::new(MyVerify, config.clone()).authorization()) .wrap(
VerifySignature::new(MyVerify, config.clone())
.authorization()
.optional(),
)
.route("/", web::post().to(index)) .route("/", web::post().to(index))
}) })
.bind("127.0.0.1:8010")? .bind("127.0.0.1:8010")?

View file

@ -1,9 +1,9 @@
use actix_web::{ use actix_web::{
dev::{Body, Service, ServiceRequest, ServiceResponse, Transform}, dev::{Body, Payload, Service, ServiceRequest, ServiceResponse, Transform},
error::PayloadError, error::PayloadError,
http::header::HeaderValue, http::header::HeaderValue,
web::Bytes, web::Bytes,
HttpMessage, HttpResponse, ResponseError, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
}; };
use failure::Fail; use failure::Fail;
use futures::{ use futures::{
@ -15,9 +15,10 @@ use std::{cell::RefCell, rc::Rc};
use super::{DigestPart, DigestVerify}; use super::{DigestPart, DigestVerify};
#[derive(Copy, Clone, Debug)]
pub struct DigestVerified;
pub struct VerifyDigest<T>(bool, T); pub struct VerifyDigest<T>(bool, T);
pub struct VerifyMiddleware<T, S>(Rc<RefCell<S>>, bool, T); pub struct VerifyMiddleware<T, S>(Rc<RefCell<S>>, bool, T);
#[derive(Debug, Fail)] #[derive(Debug, Fail)]
#[fail(display = "Error verifying digest")] #[fail(display = "Error verifying digest")]
pub struct VerifyError; pub struct VerifyError;
@ -35,6 +36,19 @@ where
} }
} }
impl FromRequest for DigestVerified {
type Error = VerifyError;
type Future = Result<Self, Self::Error>;
type Config = ();
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
req.extensions()
.get::<Self>()
.map(|s| *s)
.ok_or(VerifyError)
}
}
impl<T, S> Transform<S> for VerifyDigest<T> impl<T, S> Transform<S> for VerifyDigest<T>
where where
T: DigestVerify + Clone + 'static, T: DigestVerify + Clone + 'static,
@ -98,6 +112,8 @@ where
.into(), .into(),
); );
req.extensions_mut().insert(DigestVerified);
Either::A(service.borrow_mut().call(req)) Either::A(service.borrow_mut().call(req))
} else { } else {
Either::B(err(VerifyError.into())) Either::B(err(VerifyError.into()))

View file

@ -16,13 +16,15 @@ pub mod create;
pub mod middleware; pub mod middleware;
pub mod prelude { pub mod prelude {
pub use crate::{ pub use crate::{
middleware::VerifySignature, verify::Unverified, Config, Sign, SignatureVerify, Verify, middleware::{SignatureVerified, VerifySignature},
VerifyError, verify::Unverified,
Config, Sign, SignatureVerify, Verify, VerifyError,
}; };
#[cfg(feature = "digest")] #[cfg(feature = "digest")]
pub use crate::digest::{ pub use crate::digest::{
middleware::VerifyDigest, DigestClient, DigestCreate, DigestPart, DigestVerify, SignExt, middleware::{DigestVerified, VerifyDigest},
DigestClient, DigestCreate, DigestPart, DigestVerify, SignExt,
}; };
pub use actix_web::http::header::{InvalidHeaderValue, ToStrError}; pub use actix_web::http::header::{InvalidHeaderValue, ToStrError};

View file

@ -1,7 +1,6 @@
use actix_web::{ use actix_web::{
body::Body, dev::{Body, Payload, Service, ServiceRequest, ServiceResponse, Transform},
dev::{Service, ServiceRequest, ServiceResponse, Transform}, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
HttpResponse, ResponseError,
}; };
use failure::Fail; use failure::Fail;
use futures::{ use futures::{
@ -12,6 +11,8 @@ use std::{cell::RefCell, rc::Rc};
use crate::{Config, SignatureVerify}; use crate::{Config, SignatureVerify};
#[derive(Copy, Clone, Debug)]
pub struct SignatureVerified;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct VerifySignature<T>(T, Config, HeaderKind, bool); pub struct VerifySignature<T>(T, Config, HeaderKind, bool);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -84,6 +85,7 @@ where
.from_err::<actix_web::Error>() .from_err::<actix_web::Error>()
.and_then(move |verified| { .and_then(move |verified| {
if verified { if verified {
req.extensions_mut().insert(SignatureVerified);
Either::A(service.borrow_mut().call(req)) Either::A(service.borrow_mut().call(req))
} else { } else {
Either::B(err(VerifyError.into())) Either::B(err(VerifyError.into()))
@ -103,6 +105,19 @@ impl HeaderKind {
} }
} }
impl FromRequest for SignatureVerified {
type Error = VerifyError;
type Future = Result<Self, Self::Error>;
type Config = ();
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
req.extensions()
.get::<Self>()
.map(|s| *s)
.ok_or(VerifyError)
}
}
impl<T, S> Transform<S> for VerifySignature<T> impl<T, S> Transform<S> for VerifySignature<T>
where where
T: SignatureVerify + Clone + 'static, T: SignatureVerify + Clone + 'static,