Actually hashed passwords
This commit is contained in:
parent
fa92459b96
commit
6d20e0757b
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -114,6 +114,12 @@ version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64ct"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -831,12 +837,35 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "password-hash"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22"
|
checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
"password-hash",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
@ -1436,6 +1465,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
"pbkdf2",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tera",
|
"tera",
|
||||||
|
|
|
@ -8,6 +8,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.61"
|
anyhow = "1.0.61"
|
||||||
axum = "0.5.15"
|
axum = "0.5.15"
|
||||||
|
pbkdf2 = "0.11.0"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
sqlx = { version = "0.6.1", features = ["runtime-tokio-rustls", "postgres"] }
|
sqlx = { version = "0.6.1", features = ["runtime-tokio-rustls", "postgres"] }
|
||||||
tera = "1.16.0"
|
tera = "1.16.0"
|
||||||
|
|
|
@ -18,7 +18,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.await?,
|
.await?,
|
||||||
);
|
);
|
||||||
|
|
||||||
sqlx::query("create table if not exists users(id serial primary key, username text not null, password_hash text not null)").execute(&*pool).await?;
|
sqlx::query("create table if not exists users(id serial primary key, username text not null unique, password_hash text not null)").execute(&*pool).await?;
|
||||||
|
|
||||||
let mut tera = Arc::new(Tera::new("templates/**/*.html")?);
|
let mut tera = Arc::new(Tera::new("templates/**/*.html")?);
|
||||||
|
|
||||||
|
|
17
src/users.rs
17
src/users.rs
|
@ -2,6 +2,10 @@ use axum::extract::Extension;
|
||||||
use axum::extract::Form;
|
use axum::extract::Form;
|
||||||
use axum::response::Html;
|
use axum::response::Html;
|
||||||
use axum::response::Redirect;
|
use axum::response::Redirect;
|
||||||
|
use pbkdf2::{
|
||||||
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
||||||
|
Pbkdf2,
|
||||||
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::{Pool, Postgres};
|
use sqlx::{Pool, Postgres};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -18,9 +22,20 @@ pub async fn create_user(
|
||||||
Form(data): Form<RawUser>,
|
Form(data): Form<RawUser>,
|
||||||
Extension(pool): Extension<Arc<Pool<Postgres>>>,
|
Extension(pool): Extension<Arc<Pool<Postgres>>>,
|
||||||
) -> Result<Redirect, String> {
|
) -> Result<Redirect, String> {
|
||||||
|
let handle = tokio::task::spawn_blocking(move || {
|
||||||
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
|
let password_hash = Pbkdf2.hash_password(data.password.as_bytes(), &salt);
|
||||||
|
|
||||||
|
password_hash
|
||||||
|
.map(|p| p.to_string())
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
});
|
||||||
|
|
||||||
|
let hash = handle.await.map_err(|e| e.to_string())??;
|
||||||
|
|
||||||
sqlx::query("INSERT INTO users (username, password_hash) VALUES ($1, $2)")
|
sqlx::query("INSERT INTO users (username, password_hash) VALUES ($1, $2)")
|
||||||
.bind(data.username)
|
.bind(data.username)
|
||||||
.bind(data.password)
|
.bind(hash)
|
||||||
.execute(&*pool)
|
.execute(&*pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
Loading…
Reference in a new issue