mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 16:02:59 +01:00
Merge pull request #170 from adwhit/private-cookies
Public, signed and private cookies
This commit is contained in:
commit
458e6bdcc2
@ -23,6 +23,8 @@
|
||||
|
||||
* Fix logger request duration calculation #152
|
||||
|
||||
* Add `signed` and `private` `CookieSessionBackend`s
|
||||
|
||||
|
||||
## 0.4.10 (2018-03-20)
|
||||
|
||||
|
@ -105,7 +105,7 @@ fn main() {
|
||||
.middleware(middleware::Logger::default())
|
||||
// cookie session middleware
|
||||
.middleware(middleware::SessionStorage::new(
|
||||
middleware::CookieSessionBackend::new(&[0; 32]).secure(false)
|
||||
middleware::CookieSessionBackend::signed(&[0; 32]).secure(false)
|
||||
))
|
||||
// register favicon
|
||||
.resource("/favicon.ico", |r| r.f(favicon))
|
||||
|
@ -163,14 +163,17 @@ used with different backend types to store session data in different backends.
|
||||
> can be added.
|
||||
|
||||
[**CookieSessionBackend**](../actix_web/middleware/struct.CookieSessionBackend.html)
|
||||
uses signed cookies as session storage. `CookieSessionBackend` creates sessions which
|
||||
uses cookies as session storage. `CookieSessionBackend` creates sessions which
|
||||
are limited to storing fewer than 4000 bytes of data, as the payload must fit into a
|
||||
single cookie. An internal server error is generated if a session contains more than 4000 bytes.
|
||||
|
||||
You need to pass a random value to the constructor of `CookieSessionBackend`.
|
||||
This is a private key for cookie session. When this value is changed, all session data is lost.
|
||||
A cookie may have a security policy of *signed* or *private*. Each has a respective `CookieSessionBackend` constructor.
|
||||
|
||||
A *signed* cookie may be viewed but not modified by the client. A *private* cookie may neither be viewed nor modified by the client.
|
||||
|
||||
The constructors take a key as an argument. This is the private key for cookie session - when this value is changed, all session data is lost.
|
||||
|
||||
|
||||
> **Note**: anything you write into the session is visible by the user, but it is not modifiable.
|
||||
|
||||
In general, you create a
|
||||
`SessionStorage` middleware and initialize it with specific backend implementation,
|
||||
@ -203,7 +206,7 @@ fn main() {
|
||||
server::new(
|
||||
|| App::new()
|
||||
.middleware(SessionStorage::new( // <- create session middleware
|
||||
CookieSessionBackend::new(&[0; 32]) // <- create cookie session backend
|
||||
CookieSessionBackend::signed(&[0; 32]) // <- create signed cookie session backend
|
||||
.secure(false)
|
||||
)))
|
||||
.bind("127.0.0.1:59880").unwrap()
|
||||
|
@ -121,7 +121,7 @@ unsafe impl Sync for SessionImplBox {}
|
||||
/// fn main() {
|
||||
/// let app = App::new().middleware(
|
||||
/// SessionStorage::new( // <- create session middleware
|
||||
/// CookieSessionBackend::new(&[0; 32]) // <- create cookie session backend
|
||||
/// CookieSessionBackend::signed(&[0; 32]) // <- create cookie session backend
|
||||
/// .secure(false))
|
||||
/// );
|
||||
/// }
|
||||
@ -257,8 +257,14 @@ impl SessionImpl for CookieSession {
|
||||
}
|
||||
}
|
||||
|
||||
enum CookieSecurity {
|
||||
Signed,
|
||||
Private
|
||||
}
|
||||
|
||||
struct CookieSessionInner {
|
||||
key: Key,
|
||||
security: CookieSecurity,
|
||||
name: String,
|
||||
path: String,
|
||||
domain: Option<String>,
|
||||
@ -268,14 +274,16 @@ struct CookieSessionInner {
|
||||
|
||||
impl CookieSessionInner {
|
||||
|
||||
fn new(key: &[u8]) -> CookieSessionInner {
|
||||
fn new(key: &[u8], security: CookieSecurity) -> CookieSessionInner {
|
||||
CookieSessionInner {
|
||||
key: Key::from_master(key),
|
||||
security: security,
|
||||
name: "actix-session".to_owned(),
|
||||
path: "/".to_owned(),
|
||||
domain: None,
|
||||
secure: true,
|
||||
max_age: None }
|
||||
max_age: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_cookie(&self, resp: &mut HttpResponse, state: &HashMap<String, String>) -> Result<()> {
|
||||
@ -299,7 +307,11 @@ impl CookieSessionInner {
|
||||
}
|
||||
|
||||
let mut jar = CookieJar::new();
|
||||
jar.signed(&self.key).add(cookie);
|
||||
|
||||
match self.security {
|
||||
CookieSecurity::Signed => jar.signed(&self.key).add(cookie),
|
||||
CookieSecurity::Private => jar.private(&self.key).add(cookie),
|
||||
}
|
||||
|
||||
for cookie in jar.delta() {
|
||||
let val = HeaderValue::from_str(&cookie.to_string())?;
|
||||
@ -315,7 +327,12 @@ impl CookieSessionInner {
|
||||
if cookie.name() == self.name {
|
||||
let mut jar = CookieJar::new();
|
||||
jar.add_original(cookie.clone());
|
||||
if let Some(cookie) = jar.signed(&self.key).get(&self.name) {
|
||||
|
||||
let cookie_opt = match self.security {
|
||||
CookieSecurity::Signed => jar.signed(&self.key).get(&self.name),
|
||||
CookieSecurity::Private => jar.private(&self.key).get(&self.name),
|
||||
};
|
||||
if let Some(cookie) = cookie_opt {
|
||||
if let Ok(val) = serde_json::from_str(cookie.value()) {
|
||||
return val;
|
||||
}
|
||||
@ -327,18 +344,24 @@ impl CookieSessionInner {
|
||||
}
|
||||
}
|
||||
|
||||
/// Use signed cookies as session storage.
|
||||
/// Use cookies for session storage.
|
||||
///
|
||||
/// `CookieSessionBackend` creates sessions which are limited to storing
|
||||
/// fewer than 4000 bytes of data (as the payload must fit into a single cookie).
|
||||
/// Internal server error get generated if session contains more than 4000 bytes.
|
||||
/// An Internal Server Error is generated if the session contains more than 4000 bytes.
|
||||
///
|
||||
/// You need to pass a random value to the constructor of `CookieSessionBackend`.
|
||||
/// This is private key for cookie session, When this value is changed, all session data is lost.
|
||||
/// A cookie may have a security policy of *signed* or *private*. Each has a respective `CookieSessionBackend` constructor.
|
||||
///
|
||||
/// Note that whatever you write into your session is visible by the user (but not modifiable).
|
||||
/// A *signed* cookie is stored on the client as plaintext alongside
|
||||
/// a signature such that the cookie may be viewed but not modified by the client.
|
||||
///
|
||||
/// A *private* cookie is stored on the client as encrypted text
|
||||
/// such that it may neither be viewed nor modified by the client.
|
||||
///
|
||||
/// The constructors take a key as an argument.
|
||||
/// This is the private key for cookie session - when this value is changed, all session data is lost.
|
||||
/// The constructors will panic if the key is less than 32 bytes in length.
|
||||
///
|
||||
/// Constructor panics if key length is less than 32 bytes.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -347,7 +370,7 @@ impl CookieSessionInner {
|
||||
/// use actix_web::middleware::CookieSessionBackend;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let backend: CookieSessionBackend = CookieSessionBackend::new(&[0; 32])
|
||||
/// let backend: CookieSessionBackend = CookieSessionBackend::signed(&[0; 32])
|
||||
/// .domain("www.rust-lang.org")
|
||||
/// .name("actix_session")
|
||||
/// .path("/")
|
||||
@ -358,12 +381,20 @@ pub struct CookieSessionBackend(Rc<CookieSessionInner>);
|
||||
|
||||
impl CookieSessionBackend {
|
||||
|
||||
/// Construct new `CookieSessionBackend` instance.
|
||||
/// Construct new *signed* `CookieSessionBackend` instance.
|
||||
///
|
||||
/// Panics if key length is less than 32 bytes.
|
||||
pub fn new(key: &[u8]) -> CookieSessionBackend {
|
||||
pub fn signed(key: &[u8]) -> CookieSessionBackend {
|
||||
CookieSessionBackend(
|
||||
Rc::new(CookieSessionInner::new(key)))
|
||||
Rc::new(CookieSessionInner::new(key, CookieSecurity::Signed)))
|
||||
}
|
||||
|
||||
/// Construct new *private* `CookieSessionBackend` instance.
|
||||
///
|
||||
/// Panics if key length is less than 32 bytes.
|
||||
pub fn private(key: &[u8]) -> CookieSessionBackend {
|
||||
CookieSessionBackend(
|
||||
Rc::new(CookieSessionInner::new(key, CookieSecurity::Private)))
|
||||
}
|
||||
|
||||
/// Sets the `path` field in the session cookie being built.
|
||||
@ -385,6 +416,9 @@ impl CookieSessionBackend {
|
||||
}
|
||||
|
||||
/// 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) -> CookieSessionBackend {
|
||||
Rc::get_mut(&mut self.0).unwrap().secure = value;
|
||||
self
|
||||
|
Loading…
Reference in New Issue
Block a user