From 0880718125230a1aa03ae314e099b40da4d52786 Mon Sep 17 00:00:00 2001 From: yly Date: Thu, 14 Mar 2024 22:51:02 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Cookie=E8=AE=BE=E7=BD=AE=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 2 -- src/services/auth.rs | 18 ++++++++++- src/services/mod.rs | 74 ++++++++++---------------------------------- 3 files changed, 33 insertions(+), 61 deletions(-) diff --git a/src/main.rs b/src/main.rs index e1663ab..d7d2cd6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,8 +19,6 @@ pub mod config; pub mod controllers; pub mod entities; pub mod services; -use config::{HOME_URL, PORT}; - use crate::config::*; #[tokio::main] async fn main() { diff --git a/src/services/auth.rs b/src/services/auth.rs index 0a46d85..7b08d53 100644 --- a/src/services/auth.rs +++ b/src/services/auth.rs @@ -4,11 +4,13 @@ use std::sync::Arc; use std::time::Duration; use axum::extract::State; +use axum::response::Redirect; use axum::{ extract::{Json, Path}, http::StatusCode, response::IntoResponse, }; +use tower_cookies::cookie::SameSite; use std::time::Instant; use tower_cookies::{Cookie, Cookies}; use tower_sessions::Session; @@ -411,9 +413,23 @@ pub async fn finish_authentication( uuid, expires ); + + let original_uri = cookies.get("OriginalURL"); let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), uuid.to_string()); new_cookie.set_domain(COOKIE_DOMAIN.to_string()); + new_cookie.set_http_only(true); + new_cookie.set_path("/"); + new_cookie.set_same_site(SameSite::None); + new_cookie.set_secure(Some(true)); cookies.add(new_cookie); + // 从Cookie中恢复重定向信息 + match original_uri { + Some(redirect) => return Ok(Redirect::to(redirect.value())), + _ => (), + }; + // 处理完成重定向后,清除Cookie + cookies.remove(Cookie::new("OriginalURL", "")); + tracing::info!("Passkey登录成功,设置Cookie for {}", COOKIE_DOMAIN.to_string()); info!("从passkey登录创建了新Session{},过期时间{}s后",uuid,*SESSION_ACTIVE_TIME); StatusCode::OK } @@ -424,5 +440,5 @@ pub async fn finish_authentication( }; info!("Authentication Successful!"); - Ok(res) + Err(res.to_string()) } diff --git a/src/services/mod.rs b/src/services/mod.rs index adfbc13..984f186 100644 --- a/src/services/mod.rs +++ b/src/services/mod.rs @@ -1,25 +1,21 @@ -use axum::extract::Query; use axum::http::{HeaderMap, HeaderValue}; use axum::response::{Html, Redirect}; use axum::{extract::State, http::StatusCode, response::IntoResponse, Form}; use minijinja::{context, Environment}; +use tower_cookies::cookie::SameSite; - - +use std::borrow::BorrowMut; use std::sync::Arc; use std::time::{Duration, Instant}; -use std::borrow::BorrowMut; -use std::{collections::HashMap, str::FromStr}; +use std::str::FromStr; use tower_cookies::{Cookie, Cookies}; - use uuid::Uuid; +use super::config::{COOKIE_DOMAIN, COOKIE_NAME, LOGIN_PAGE_HTML, SESSION_ACTIVE_TIME}; use crate::config::{HOME_URL, REGISTER_PAGE_HTML}; use crate::{ServerState, UserLoginForm}; -use super::config::{COOKIE_DOMAIN, COOKIE_NAME, LOGIN_PAGE_HTML, SESSION_ACTIVE_TIME}; - pub async fn gc_task(state: Arc) { let mut interval = tokio::time::interval(Duration::from_secs(*SESSION_ACTIVE_TIME)); @@ -47,7 +43,9 @@ pub async fn auth_otp( let mut locked = state.session.lock().await; if let std::collections::hash_map::Entry::Occupied(mut e) = locked.entry(s) { // FIX, when accessed /auth with correct cookie, the cookie's expiration is delayed - let Some(v) = Some(e.insert(Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME))) else { + let Some(v) = + Some(e.insert(Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME))) + else { tracing::info!("session:{} extended", session_token.value()); return StatusCode::UNAUTHORIZED; }; @@ -90,10 +88,14 @@ pub async fn login( let original_uri = cookies.get("OriginalURL"); let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), s.to_string()); new_cookie.set_domain(COOKIE_DOMAIN.to_string()); + new_cookie.set_http_only(true); + new_cookie.set_path("/"); + new_cookie.set_same_site(SameSite::None); + new_cookie.set_secure(Some(true)); cookies.add(new_cookie); - tracing::info!("登录成功,设置Cookie for {}",COOKIE_DOMAIN.to_string()); + tracing::info!("登录成功,设置Cookie for {}", COOKIE_DOMAIN.to_string()); // 从Cookie中恢复重定向信息 - let res = match original_uri{ + let res = match original_uri { Some(redirect) => Ok(Redirect::to(redirect.value())), None => Err((StatusCode::ACCEPTED, "ok")), }; @@ -121,7 +123,8 @@ pub async fn login_page(headers: HeaderMap) -> impl IntoResponse { pub async fn register_page(headers: HeaderMap) -> impl IntoResponse { tracing::info!("Headers: {:#?}", headers); let mut env = Environment::new(); - env.add_template("register.html", REGISTER_PAGE_HTML).unwrap(); + env.add_template("register.html", REGISTER_PAGE_HTML) + .unwrap(); let template = env.get_template("register.html").unwrap(); Html( template @@ -158,49 +161,4 @@ pub async fn gc(state: Arc) -> Result<(), String> { Ok(()) } -pub async fn login_with_passkey( - State(state): State>, - cookies: Cookies, - Query(params): Query>, - Form(frm): Form, -) -> Result { - let conn = state.db.acquire().await; - let Ok(mut conn) = conn else { - return Err((StatusCode::BAD_GATEWAY, "db连接错误")); - }; - tracing::info!("开始使用passkey登陆{:?}", &frm); - let target = sqlx::query_as::<_, UserLoginForm>( - r" - SELECT NAME, KEY FROM USERS WHERE NAME = ? - ", - ) - .bind(frm.username) - .fetch_optional(&mut *conn) - .await; - tracing::info!("数据库返回 {:?}", &target); - - if let Ok(Some(target)) = target { - if check_otp(target.otp, frm.otp) { - let s = Uuid::new_v4(); - let mut locked = state.session.lock().await; - locked.insert( - s, - Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME), - ); - let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), s.to_string()); - new_cookie.set_domain(COOKIE_DOMAIN.to_string()); - cookies.add(new_cookie); - if let Some(original_uri) = params.get("original_url") { - return Ok(Redirect::to(original_uri)); - } - - return Err((StatusCode::ACCEPTED, "ok")); - } else { - return Err((StatusCode::UNAUTHORIZED, "wrong password")); - } - } - Err((StatusCode::BAD_GATEWAY, "unreachable")) - - -} -pub mod auth; \ No newline at end of file +pub mod auth;