DONE,处理重定向
This commit is contained in:
parent
2b7932dd49
commit
d119f958f6
@ -11,7 +11,6 @@ server {
|
||||
proxy_set_header X-Original-URI $scheme://$host$request_uri;
|
||||
proxy_pass http://protected/;
|
||||
}
|
||||
location
|
||||
location = /aaron/auth {
|
||||
internal;
|
||||
proxy_pass http://localhost:3000/auth;
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Login</h1>
|
||||
<form action="{{ home_url|safe }}/login{{ url }}" method="POST">
|
||||
<form action="{{ home_url|safe }}/login" method="POST">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
<label for="password">Password:</label>
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use std::env;
|
||||
pub const COOKIE_NAME: Lazy<String> =
|
||||
pub static COOKIE_NAME: Lazy<String> =
|
||||
Lazy::new(|| env::var("COOKIE_NAME").unwrap_or("aaron_auth".to_string()));
|
||||
pub const SESSION_ACTIVE_TIME: Lazy<u64> = Lazy::new(|| {
|
||||
pub static SESSION_ACTIVE_TIME: Lazy<u64> = Lazy::new(|| {
|
||||
env::var("SESSION_ACTIVE_TIME")
|
||||
.ok()
|
||||
.and_then(|value| value.parse().ok())
|
||||
.unwrap_or(600)
|
||||
});
|
||||
pub const COOKIE_DOMAIN: Lazy<String> =
|
||||
pub static COOKIE_DOMAIN: Lazy<String> =
|
||||
Lazy::new(|| env::var("DOMAIN").ok().unwrap_or(".aaronhu.cn".to_owned()));
|
||||
pub const LOGIN_PAGE_HTML: &str = include_str!("../loginpage.html");
|
||||
pub const REGISTER_PAGE_HTML: &str = include_str!("../register.html");
|
||||
pub const PORT: Lazy<String> = Lazy::new(|| env::var("PORT").unwrap_or("3000".to_string()));
|
||||
pub static LOGIN_PAGE_HTML: &str = include_str!("../loginpage.html");
|
||||
pub static REGISTER_PAGE_HTML: &str = include_str!("../register.html");
|
||||
pub static PORT: Lazy<String> = Lazy::new(|| env::var("PORT").unwrap_or("3000".to_string()));
|
||||
// 部署此应用的URL,默认为/aaron
|
||||
pub const HOME_URL: Lazy<String> =
|
||||
pub static HOME_URL: Lazy<String> =
|
||||
Lazy::new(|| env::var("HOME_URL").unwrap_or("/aaron".to_owned()));
|
||||
pub const DATABASE_URL: Lazy<String> =
|
||||
pub static DATABASE_URL: Lazy<String> =
|
||||
Lazy::new(|| env::var("DATABASE_URL").unwrap_or("".to_owned()));
|
||||
pub const RP_ID: Lazy<String> =
|
||||
pub static RP_ID: Lazy<String> =
|
||||
Lazy::new(|| env::var("RP_ID").unwrap_or("localhost".to_owned()));
|
||||
pub const RP_ORIGIN: Lazy<String> =
|
||||
pub static RP_ORIGIN: Lazy<String> =
|
||||
Lazy::new(|| env::var("RP_ORIGIN").unwrap_or("http://localhost:8080".to_owned()));
|
||||
pub const RP_NAME: Lazy<String> =
|
||||
pub static RP_NAME: Lazy<String> =
|
||||
Lazy::new(|| env::var("RP_NAME").unwrap_or("Localhost".to_owned()));
|
||||
|
||||
@ -20,11 +20,11 @@ pub struct ServerState {
|
||||
impl ServerState {
|
||||
pub async fn new() -> Self {
|
||||
// Effective domain name.
|
||||
let rp_id = RP_ID;
|
||||
let rp_id = &RP_ID;
|
||||
// Url containing the effective domain name
|
||||
// MUST include the port number!
|
||||
let rp_origin = Url::parse(&RP_ORIGIN).expect("Invalid URL");
|
||||
let builder = WebauthnBuilder::new(&rp_id, &rp_origin).expect("Invalid configuration");
|
||||
let builder = WebauthnBuilder::new(rp_id, &rp_origin).expect("Invalid configuration");
|
||||
|
||||
// Now, with the builder you can define other options.
|
||||
// Set a "nice" relying party name. Has no security properties and
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
|
||||
use axum::{routing::{get, get_service, post, Route}, Router};
|
||||
use axum::{routing::{get, post}, Router};
|
||||
use entities::*;
|
||||
|
||||
use services::{auth::{self, finish_authentication, start_authentication}, gc_task, login, login_page, register_page};
|
||||
@ -10,7 +10,6 @@ use std::sync::Arc;
|
||||
use tower_cookies::CookieManagerLayer;
|
||||
use tower_http::trace::{self, TraceLayer};
|
||||
use tower_sessions::{Expiry, MemoryStore, SessionManagerLayer};
|
||||
use tower_http::services::{ServeDir, ServeFile};
|
||||
use tracing::Level;
|
||||
|
||||
pub mod config;
|
||||
|
||||
@ -3,7 +3,6 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use axum::debug_handler;
|
||||
use axum::extract::State;
|
||||
use axum::{
|
||||
extract::{Json, Path},
|
||||
@ -63,12 +62,15 @@ use crate::ServerState;
|
||||
// TODO - Improve error handling and messages
|
||||
fn auth_user(cookie_content: String, session_table: &mut HashMap<Uuid, Instant>) -> bool {
|
||||
let Ok(uuid) = Uuid::parse_str(&cookie_content) else {
|
||||
info!("此用户Session不在表中");
|
||||
return false;
|
||||
};
|
||||
let Some(expire) = session_table.get(&uuid) else {
|
||||
info!("此用户Session已过期");
|
||||
return false;
|
||||
};
|
||||
if *expire <= Instant::now() {
|
||||
info!("此用户Session已过期");
|
||||
return false;
|
||||
}
|
||||
session_table.insert(
|
||||
@ -76,7 +78,7 @@ fn auth_user(cookie_content: String, session_table: &mut HashMap<Uuid, Instant>)
|
||||
Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME),
|
||||
);
|
||||
tracing::info!("valid cookie {}", uuid);
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
pub async fn start_register(
|
||||
@ -188,6 +190,7 @@ pub async fn finish_register(
|
||||
info!("Passkey 正常");
|
||||
let uid = &user_id.to_string();
|
||||
let username = &user_name.to_string();
|
||||
info!("检查用户是否存在");
|
||||
// Check if the user_id already exists
|
||||
let record = sqlx::query!("SELECT COUNT(KEY) AS count FROM users WHERE KEY = $1;", uid)
|
||||
.fetch_one(pool)
|
||||
@ -226,13 +229,14 @@ pub async fn finish_register(
|
||||
.rows_affected()
|
||||
!= 1
|
||||
{
|
||||
error!("将用户凭据持久化时失败");
|
||||
return Err(WebauthnError::AuthenticationFailure.to_string());
|
||||
}
|
||||
|
||||
StatusCode::OK
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("challenge_register -> {:?}", e);
|
||||
error!("challenge_register -> {:?}", e);
|
||||
StatusCode::BAD_REQUEST
|
||||
}
|
||||
};
|
||||
@ -277,7 +281,7 @@ pub async fn start_authentication(
|
||||
info!("Start Authentication");
|
||||
let pool = &state.db;
|
||||
// Remove any previous authentication that may have occurred from the session.
|
||||
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("auth_state");
|
||||
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("auth_state").await;
|
||||
let user_id = sqlx::query!("SELECT KEY FROM users WHERE NAME = $1;", user_name)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
@ -342,7 +346,7 @@ pub async fn finish_authentication(
|
||||
.unwrap()
|
||||
.ok_or(WebauthnError::AuthenticationFailure.to_string())?;
|
||||
|
||||
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("auth_state");
|
||||
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("auth_state").await;
|
||||
|
||||
let res = match state
|
||||
.webauthn
|
||||
|
||||
@ -62,7 +62,6 @@ pub async fn auth_otp(
|
||||
pub async fn login(
|
||||
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;
|
||||
@ -88,14 +87,18 @@ pub async fn login(
|
||||
s,
|
||||
Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME),
|
||||
);
|
||||
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());
|
||||
cookies.add(new_cookie);
|
||||
if let Some(original_uri) = params.get("original_url") {
|
||||
return Ok(Redirect::to(original_uri));
|
||||
}
|
||||
|
||||
return Err((StatusCode::ACCEPTED, "ok"));
|
||||
// 从Cookie中恢复重定向信息
|
||||
let res = match original_uri{
|
||||
Some(redirect) => Ok(Redirect::to(redirect.value())),
|
||||
None => Err((StatusCode::ACCEPTED, "ok")),
|
||||
};
|
||||
// 处理完成重定向后,清除Cookie
|
||||
cookies.remove(Cookie::new("OriginalURL", ""));
|
||||
return res;
|
||||
} else {
|
||||
return Err((StatusCode::UNAUTHORIZED, "wrong password"));
|
||||
}
|
||||
@ -108,22 +111,9 @@ pub async fn login_page(headers: HeaderMap<HeaderValue>) -> impl IntoResponse {
|
||||
let mut env = Environment::new();
|
||||
env.add_template("login.html", LOGIN_PAGE_HTML).unwrap();
|
||||
let template = env.get_template("login.html").unwrap();
|
||||
if let Some(original_uri) = headers.get("X-Original-URI") {
|
||||
if let Ok(uri) = original_uri.to_str() {
|
||||
tracing::info!("redirect to {}", uri);
|
||||
if !uri.is_empty() {
|
||||
let uri = "?original_url=".to_owned() + uri;
|
||||
return Html(
|
||||
template
|
||||
.render(context! { url => uri, home_url => HOME_URL.to_string() })
|
||||
.unwrap_or("Error".to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Html(
|
||||
template
|
||||
.render(context! { url => String::new(), home_url => HOME_URL.to_string() })
|
||||
.render(context! { home_url => HOME_URL.to_string() })
|
||||
.unwrap_or("Error".to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user