Skip to content
Clone
d6dc02f
87 lines 2.5 KB Rust
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SessionConfig {
pub cookie_name: String,
pub max_age: i64,
#[serde(default = "default_anonymous_max_age")]
pub anonymous_max_age: i64,
pub path: Option<String>,
pub domain: Option<String>,
pub secure: bool,
pub same_site: SameSite,
#[serde(default)]
pub trust_proxy: bool,
#[serde(default = "default_recheck_secs")]
pub recheck_secs: u64,
}
fn default_anonymous_max_age() -> i64 {
300
}
fn default_recheck_secs() -> u64 {
60
}
impl Default for SessionConfig {
fn default() -> Self {
Self {
cookie_name: "session".to_owned(),
max_age: 2_592_000,
anonymous_max_age: default_anonymous_max_age(),
path: Some("/".to_owned()),
domain: None,
secure: false,
same_site: SameSite::default(),
trust_proxy: false,
recheck_secs: default_recheck_secs(),
}
}
}
/// `secure=false` 只允许开发环境:回环监听,或显式 `KENOAUTH_ALLOW_INSECURE_COOKIE=1`。
pub fn ensure_secure_cookie(
secure: bool,
http_addr: std::net::SocketAddr,
allow_insecure_env: bool,
) -> Result<(), String> {
if secure || allow_insecure_env || http_addr.ip().is_loopback() {
return Ok(());
}
Err(format!(
"session.secure=false is only allowed in development; {http_addr} is not a loopback \
address. Set session.secure=true, or set KENOAUTH_ALLOW_INSECURE_COOKIE=1 to confirm"
))
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum SameSite {
Strict,
/// 浏览器与 RFC626bis 的实际默认值;显式配置 None 时需自行保证 Secure。
#[default]
Lax,
None,
}
impl crate::loader::Section for SessionConfig {
const KEY: &'static str = "session";
}
#[cfg(test)]
mod tests {
use super::*;
fn addr(ip: [u8; 4]) -> std::net::SocketAddr {
std::net::SocketAddr::from((ip, 18081))
}
#[test]
fn insecure_cookie_is_only_allowed_in_development() {
assert!(ensure_secure_cookie(true, addr([0, 0, 0, 0]), false).is_ok());
assert!(ensure_secure_cookie(false, addr([127, 0, 0, 1]), false).is_ok());
assert!(ensure_secure_cookie(false, addr([192, 168, 1, 10]), true).is_ok());
let error = ensure_secure_cookie(false, addr([0, 0, 0, 0]), false).unwrap_err();
assert!(error.contains("session.secure"));
}
}