重定向实现
This commit is contained in:
parent
a9fd136a55
commit
168619ef63
148
Cargo.lock
generated
148
Cargo.lock
generated
@ -45,6 +45,58 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134"
|
||||
dependencies = [
|
||||
"askama_derive",
|
||||
"askama_escape",
|
||||
"askama_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522"
|
||||
dependencies = [
|
||||
"askama_shared",
|
||||
"proc-macro2",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_escape"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||
|
||||
[[package]]
|
||||
name = "askama_shared"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d6083ccb191711e9c2b80b22ee24a8381a18524444914c746d4239e21d1afaf"
|
||||
dependencies = [
|
||||
"askama_escape",
|
||||
"humansize",
|
||||
"nom 6.1.2",
|
||||
"num-traits",
|
||||
"percent-encoding",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 1.0.109",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.74"
|
||||
@ -69,7 +121,9 @@ dependencies = [
|
||||
name = "auth"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"askama",
|
||||
"axum",
|
||||
"minijinja",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"tokio",
|
||||
@ -185,6 +239,18 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "0.19.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@ -415,6 +481,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.29"
|
||||
@ -657,6 +729,12 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "humansize"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.27"
|
||||
@ -724,6 +802,19 @@ dependencies = [
|
||||
"spin 0.5.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.149"
|
||||
@ -806,6 +897,15 @@ version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "minijinja"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f98b09920c8be9ff96a5625aca5b5db7a4f4ba025132ff7d7aacb72c0244a45"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@ -832,6 +932,19 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "6.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"funty",
|
||||
"lexical-core",
|
||||
"memchr",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@ -1064,6 +1177,12 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
@ -1374,7 +1493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"nom",
|
||||
"nom 7.1.3",
|
||||
"unicode_categories",
|
||||
]
|
||||
|
||||
@ -1572,6 +1691,12 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "stringprep"
|
||||
version = "0.1.4"
|
||||
@ -1617,6 +1742,12 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.1"
|
||||
@ -1745,6 +1876,15 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "totp-rs"
|
||||
version = "5.4.0"
|
||||
@ -2077,6 +2217,12 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.18"
|
||||
|
||||
@ -16,3 +16,5 @@ totp-rs = "5.4.0"
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
tower-http = { version = "0.4.4", features = ["trace"] }
|
||||
tracing = "0.1.40"
|
||||
askama = "0.10"
|
||||
minijinja = "1.0.9"
|
||||
|
||||
29
auth.conf
Normal file
29
auth.conf
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
upstream protected {
|
||||
server 127.0.0.1:10000;
|
||||
}
|
||||
server {
|
||||
listen 8080;
|
||||
location / {
|
||||
auth_request /auth;
|
||||
set $original_full_url $scheme://$host$request_uri;
|
||||
error_page 401 =200 /login;
|
||||
proxy_set_header X-Original-URI $scheme://$host$request_uri;
|
||||
proxy_pass http://protected/;
|
||||
}
|
||||
location = /auth {
|
||||
internal;
|
||||
proxy_pass http://localhost:3000/auth;
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header X-Original-URI $request_uri; #可用来控制权限
|
||||
proxy_set_header X-Original-Remote-Addr $remote_addr;
|
||||
proxy_set_header X-Original-Host $host;
|
||||
}
|
||||
location /login {
|
||||
proxy_pass http://localhost:3000/login;
|
||||
proxy_set_header X-Original-Remote-Addr $remote_addr;
|
||||
proxy_set_header X-Original-Host $host;
|
||||
proxy_set_header X-Original-URI $original_full_url;
|
||||
}
|
||||
}
|
||||
@ -53,13 +53,11 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Login</h1>
|
||||
<form action="/login" method="POST">
|
||||
<form action="/login{{ url }}" method="POST">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="otp" required>
|
||||
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
50
src/main.rs
50
src/main.rs
@ -1,4 +1,4 @@
|
||||
use axum::{Extension, TypedHeader};
|
||||
use axum::extract::Query;
|
||||
use axum::response::{Html, Redirect};
|
||||
use axum::http::{Uri, HeaderMap, HeaderValue};
|
||||
use axum::{
|
||||
@ -20,6 +20,7 @@ use tower_cookies::{Cookie, CookieManagerLayer, Cookies};
|
||||
use uuid::Uuid;
|
||||
use tower_http::trace::{self, TraceLayer};
|
||||
use tracing::Level;
|
||||
use minijinja::{Environment, context};
|
||||
pub struct ServerState {
|
||||
pub db: sqlx::Pool<sqlx::Sqlite>,
|
||||
pub session: Mutex<HashMap<Uuid, Instant>>,
|
||||
@ -88,15 +89,18 @@ async fn auth(
|
||||
cookies: Cookies,
|
||||
) -> StatusCode {
|
||||
if let Some(session_token) = cookies.get(COOKIE_NAME) {
|
||||
tracing::info!("session:{}",session_token.value());
|
||||
let Ok(s) = uuid::Uuid::from_str(session_token.value()) else {
|
||||
return StatusCode::UNAUTHORIZED;
|
||||
};
|
||||
let mut locked = state.session.lock().await;
|
||||
let Some(v) = locked.insert(s,Instant::now()+Duration::from_secs(SESSION_ACTIVE_TIME)) else {
|
||||
return StatusCode::UNAUTHORIZED;
|
||||
};
|
||||
if Instant::now() < v {
|
||||
return StatusCode::OK;
|
||||
if locked.contains_key(&s) { // FIX
|
||||
let Some(v) = locked.insert(s,Instant::now()+Duration::from_secs(SESSION_ACTIVE_TIME)) else {
|
||||
return StatusCode::UNAUTHORIZED;
|
||||
};
|
||||
if Instant::now() < v {
|
||||
return StatusCode::OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return StatusCode::UNAUTHORIZED;
|
||||
@ -105,17 +109,17 @@ async fn auth(
|
||||
async fn login(
|
||||
State(state): State<Arc<ServerState>>,
|
||||
cookies: Cookies,
|
||||
headers: HeaderMap<HeaderValue>,
|
||||
Query(mut params): Query<HashMap<String, String>>,
|
||||
Form(frm): Form<UserLoginForm>,
|
||||
) -> impl IntoResponse {
|
||||
) -> Result<Redirect, (StatusCode, &'static str)> {
|
||||
let conn = state.db.acquire().await;
|
||||
let Ok(mut conn) = conn else {
|
||||
return (StatusCode::BAD_GATEWAY, "db连接错误");
|
||||
return Err((StatusCode::BAD_GATEWAY, "db连接错误"));
|
||||
};
|
||||
tracing::info!("{:?}",&frm);
|
||||
let target = sqlx::query_as::<_, UserLoginForm>(
|
||||
r#"
|
||||
SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
||||
SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
||||
"#,
|
||||
)
|
||||
.bind(frm.username)
|
||||
@ -129,17 +133,35 @@ SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
||||
let mut locked = state.session.lock().await;
|
||||
locked.insert(s.clone(), Instant::now() + Duration::from_secs(SESSION_ACTIVE_TIME));
|
||||
cookies.add(Cookie::new(COOKIE_NAME, s.to_string()));
|
||||
return (StatusCode::ACCEPTED, "ok");
|
||||
if let Some(original_uri) = params.get("original_url") {
|
||||
return Ok(Redirect::permanent(&original_uri));
|
||||
}
|
||||
|
||||
return Err((StatusCode::ACCEPTED, "ok"));
|
||||
} else {
|
||||
return (StatusCode::UNAUTHORIZED,"wrong password");
|
||||
return Err((StatusCode::UNAUTHORIZED,"wrong password"));
|
||||
}
|
||||
}
|
||||
return (StatusCode::BAD_GATEWAY, "unreachable");
|
||||
return Err((StatusCode::BAD_GATEWAY, "unreachable"));
|
||||
}
|
||||
|
||||
async fn login_page(
|
||||
headers: HeaderMap<HeaderValue>,
|
||||
)-> impl IntoResponse{
|
||||
return Html(LOGIN_PAGE_HTML);
|
||||
tracing::info!("Headers: {:#?}",headers);
|
||||
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 }).unwrap_or("Error".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
return Html(template.render(context! { url => String::new() }).unwrap_or("Error".to_string()))
|
||||
}
|
||||
|
||||
pub fn check_otp(key_from_db: String, user_input_otp: String) -> bool {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user