Fix Cookie设置问题修复

This commit is contained in:
yly 2024-03-14 22:51:02 +08:00
parent 2f58427025
commit 0880718125
3 changed files with 33 additions and 61 deletions

View File

@ -19,8 +19,6 @@ pub mod config;
pub mod controllers; pub mod controllers;
pub mod entities; pub mod entities;
pub mod services; pub mod services;
use config::{HOME_URL, PORT};
use crate::config::*; use crate::config::*;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {

View File

@ -4,11 +4,13 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use axum::extract::State; use axum::extract::State;
use axum::response::Redirect;
use axum::{ use axum::{
extract::{Json, Path}, extract::{Json, Path},
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
}; };
use tower_cookies::cookie::SameSite;
use std::time::Instant; use std::time::Instant;
use tower_cookies::{Cookie, Cookies}; use tower_cookies::{Cookie, Cookies};
use tower_sessions::Session; use tower_sessions::Session;
@ -411,9 +413,23 @@ pub async fn finish_authentication(
uuid, uuid,
expires expires
); );
let original_uri = cookies.get("OriginalURL");
let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), uuid.to_string()); let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), uuid.to_string());
new_cookie.set_domain(COOKIE_DOMAIN.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); 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); info!("从passkey登录创建了新Session{},过期时间{}s后",uuid,*SESSION_ACTIVE_TIME);
StatusCode::OK StatusCode::OK
} }
@ -424,5 +440,5 @@ pub async fn finish_authentication(
}; };
info!("Authentication Successful!"); info!("Authentication Successful!");
Ok(res) Err(res.to_string())
} }

View File

@ -1,25 +1,21 @@
use axum::extract::Query;
use axum::http::{HeaderMap, HeaderValue}; use axum::http::{HeaderMap, HeaderValue};
use axum::response::{Html, Redirect}; use axum::response::{Html, Redirect};
use axum::{extract::State, http::StatusCode, response::IntoResponse, Form}; use axum::{extract::State, http::StatusCode, response::IntoResponse, Form};
use minijinja::{context, Environment}; use minijinja::{context, Environment};
use tower_cookies::cookie::SameSite;
use std::borrow::BorrowMut;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::borrow::BorrowMut; use std::str::FromStr;
use std::{collections::HashMap, str::FromStr};
use tower_cookies::{Cookie, Cookies}; use tower_cookies::{Cookie, Cookies};
use uuid::Uuid; 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::config::{HOME_URL, REGISTER_PAGE_HTML};
use crate::{ServerState, UserLoginForm}; use crate::{ServerState, UserLoginForm};
use super::config::{COOKIE_DOMAIN, COOKIE_NAME, LOGIN_PAGE_HTML, SESSION_ACTIVE_TIME};
pub async fn gc_task(state: Arc<ServerState>) { pub async fn gc_task(state: Arc<ServerState>) {
let mut interval = tokio::time::interval(Duration::from_secs(*SESSION_ACTIVE_TIME)); 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; let mut locked = state.session.lock().await;
if let std::collections::hash_map::Entry::Occupied(mut e) = locked.entry(s) { 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 // 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()); tracing::info!("session:{} extended", session_token.value());
return StatusCode::UNAUTHORIZED; return StatusCode::UNAUTHORIZED;
}; };
@ -90,10 +88,14 @@ pub async fn login(
let original_uri = cookies.get("OriginalURL"); let original_uri = cookies.get("OriginalURL");
let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), s.to_string()); let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), s.to_string());
new_cookie.set_domain(COOKIE_DOMAIN.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); cookies.add(new_cookie);
tracing::info!("登录成功设置Cookie for {}",COOKIE_DOMAIN.to_string()); tracing::info!("登录成功设置Cookie for {}", COOKIE_DOMAIN.to_string());
// 从Cookie中恢复重定向信息 // 从Cookie中恢复重定向信息
let res = match original_uri{ let res = match original_uri {
Some(redirect) => Ok(Redirect::to(redirect.value())), Some(redirect) => Ok(Redirect::to(redirect.value())),
None => Err((StatusCode::ACCEPTED, "ok")), None => Err((StatusCode::ACCEPTED, "ok")),
}; };
@ -121,7 +123,8 @@ pub async fn login_page(headers: HeaderMap<HeaderValue>) -> impl IntoResponse {
pub async fn register_page(headers: HeaderMap<HeaderValue>) -> impl IntoResponse { pub async fn register_page(headers: HeaderMap<HeaderValue>) -> impl IntoResponse {
tracing::info!("Headers: {:#?}", headers); tracing::info!("Headers: {:#?}", headers);
let mut env = Environment::new(); 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(); let template = env.get_template("register.html").unwrap();
Html( Html(
template template
@ -158,49 +161,4 @@ pub async fn gc(state: Arc<ServerState>) -> Result<(), String> {
Ok(()) Ok(())
} }
pub async fn login_with_passkey(
State(state): State<Arc<ServerState>>,
cookies: Cookies,
Query(params): Query<HashMap<String, String>>,
Form(frm): Form<UserLoginForm>,
) -> Result<Redirect, (StatusCode, &'static str)> {
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; pub mod auth;