Skip to content
Clone
main
53 lines 1.8 KB Rust
use crate::models::users::{user_sessions, users};
use crate::session::Session;
use chrono::{Duration, Utc};
use sea_orm::{ActiveModelTrait, Set};
use uuid::Uuid;
use crate::share::crypto;
use crate::{AuthResult, AuthService};
/// 会话凭据摘要的算法标识,落在 `user_sessions.hash_key_id`。
pub const SESSION_HASH_KEY_ID: &str = "logical-session-v1";
/// 会话 ID 的摘要。会话 ID 本身即凭据,库里只存摘要。
pub fn session_token_hash(id: Uuid) -> String {
crypto::sha256_hex(id.to_string().as_bytes())
}
impl AuthService {
#[tracing::instrument(skip_all, fields(user_id = user.id, mfa = mfa, request_id = %envelope::context::resolve_request_id(request_id)))]
pub async fn bind_auth_session(
&self,
session: &Session,
user: &users::Model,
mfa: bool,
request_id: Option<&str>,
) -> AuthResult<()> {
let now = Utc::now();
let id = Uuid::now_v7();
let ttl = i64::try_from(self.session_max_age_secs())
.unwrap_or(86400)
.max(1);
user_sessions::ActiveModel {
id: Set(id),
user_id: Set(user.id),
token_hash: Set(session_token_hash(id)),
hash_key_id: Set(SESSION_HASH_KEY_ID.into()),
security_version: Set(user.security_version),
expires_at: Set(now + Duration::seconds(ttl)),
mfa_verified_at: Set(mfa.then_some(now)),
ip_address: Set(session.client_ip()?),
user_agent: Set(session.user_agent()?),
..Default::default()
}
.insert(self.db().write())
.await?;
session.set("auth_session_id", id.to_string())?;
session.set("mfa_verified", mfa)?;
session.set_user_id(user.id)?;
session.set_security_version(user.security_version)?;
session.renew();
Ok(())
}
}