actix_security_core/http/security/
middleware.rs1use std::rc::Rc;
7
8use actix_service::{Service, Transform};
9use actix_web::body::EitherBody;
10use actix_web::dev::{ServiceRequest, ServiceResponse};
11use actix_web::{Error, HttpMessage};
12use futures_util::future::{ok, LocalBoxFuture, Ready};
13
14use crate::http::security::config::{Authenticator, Authorizer};
15
16pub struct SecurityTransform<Auth, Autho> {
30 authenticator: Option<fn() -> Auth>,
31 authorizer: Option<fn() -> Autho>,
32}
33
34impl<Auth, Autho> SecurityTransform<Auth, Autho> {
35 pub fn new() -> Self {
36 SecurityTransform {
37 authorizer: None,
38 authenticator: None,
39 }
40 }
41
42 pub fn config_authenticator(mut self, authenticator: fn() -> Auth) -> Self {
43 self.authenticator = Some(authenticator);
44 self
45 }
46
47 pub fn config_authorizer(mut self, authorizer: fn() -> Autho) -> Self {
48 self.authorizer = Some(authorizer);
49 self
50 }
51}
52
53impl<Auth, Autho> Default for SecurityTransform<Auth, Autho> {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl<S, B, Auth, Autho> Transform<S, ServiceRequest> for SecurityTransform<Auth, Autho>
60where
61 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
62 S::Future: 'static,
63 B: 'static,
64 Auth: Authenticator + 'static,
65 Autho: Authorizer<B> + 'static,
66{
67 type Response = ServiceResponse<EitherBody<B>>;
68 type Error = Error;
69 type Transform = SecurityService<Auth, Autho, S>;
70 type InitError = ();
71 type Future = Ready<Result<Self::Transform, Self::InitError>>;
72
73 fn new_transform(&self, service: S) -> Self::Future {
74 let authenticator = self.authenticator.map(|f| f());
75 let authorizer = self.authorizer.map(|f| f());
76
77 ok(SecurityService {
78 authenticator,
79 authorizer,
80 service: Rc::new(service),
81 })
82 }
83}
84
85pub struct SecurityService<Auth, Autho, S> {
90 authenticator: Option<Auth>,
91 authorizer: Option<Autho>,
92 service: Rc<S>,
93}
94
95impl<Auth, Autho, S, B> Service<ServiceRequest> for SecurityService<Auth, Autho, S>
96where
97 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
98 S::Future: 'static,
99 B: 'static,
100 Auth: Authenticator,
101 Autho: Authorizer<B>,
102{
103 type Response = ServiceResponse<EitherBody<B>>;
104 type Error = Error;
105 type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
106
107 actix_web::dev::forward_ready!(service);
108
109 fn call(&self, req: ServiceRequest) -> Self::Future {
110 let service = Rc::clone(&self.service);
111
112 let user = self
114 .authenticator
115 .as_ref()
116 .and_then(|auth| auth.get_user(&req));
117
118 if let Some(ref u) = user {
121 req.extensions_mut().insert(u.clone());
122 }
123
124 if let Some(authorizer) = &self.authorizer {
126 let next = move |req: ServiceRequest| -> LocalBoxFuture<'static, Result<ServiceResponse<B>, Error>> {
128 let fut = service.call(req);
129 Box::pin(fut)
130 };
131
132 authorizer.process(req, user.as_ref(), next)
133 } else {
134 let fut = service.call(req);
136 Box::pin(async move {
137 let res = fut.await?;
138 Ok(res.map_into_left_body())
139 })
140 }
141 }
142}