9个版本
0.1.8 | 2024年6月13日 |
---|---|
0.1.7 | 2024年1月11日 |
0.1.4 | 2023年12月1日 |
0.1.3 | 2023年11月26日 |
在 身份验证 中排名第 122
每月下载 507 次
15KB
206 行
axum_jwt_ware集成指南
简单的Axum + JWT身份验证中间件,实现了登录和刷新令牌。
目标
我的目标是简化开发者/独立黑客在启动新项目时的过程,让他们能够专注于编写核心业务逻辑,而不是花费时间重写身份验证。
安装
cargo add axum_jwt_ware
使用示例
有一个标准中间件用于通过JWT验证用户 -- verify_user
中间件。其签名如下
pub async fn verify_user<B>(
mut req: Request<B>,
key: &DecodingKey,
validation: Validation,
next: Next<B>,
) -> Result<Response, AuthError>
您可以将它传递给路由层,如下所示
use axum_jwt_ware;
let app = Router::new()
.route(
"/hello",
get(hello)
.layer(middleware::from_fn(move |req, next| {
let key = axum_jwt_ware::DecodingKey::from_secret(jwt_secret.as_ref());
let validation = axum_jwt_ware::Validation::default();
async move { axum_jwt_ware::verify_user(req, &key, validation, next).await }
})),
)
登录
您可以选择实现自己的自定义登录或使用库提供的登录。提供的登录使用默认算法,只需您提供“密钥”即可。
以下是如何使用提供的登录的示例
use axum_jwt_ware::{CurrentUser, UserData};
#[derive(Clone, Copy)]
pub struct MyUserData;
impl UserData for MyUserData {
async fn get_user_by_email(&self, _email: &str) -> Option<CurrentUser> {
// Implement the logic to fetch a user by email from your database
}
}
let app = Router::new()
.route(
"/login",
post(move |body: Json<axum_jwt_ware::RequestBody>| {
let expiry_timestamp = (Utc::now() + Duration::hours(48)).timestamp();
let user_data = MyUserData;
let jwt_secret = "secret";
let refresh_secret = "refresh_secret";
axum_jwt_ware::login(
body,
user_data.clone(),
jwt_secret,
refresh_secret,
expiry_timestamp.timestamp(),
)
}),
)
如果您要实现自定义登录,请确保使用 axum_auth_ware::auth_token_encode
方法生成您的令牌。以下是一个使用RSA加密的登录示例
use axum_jwt_ware::{CurrentUser, UserData, Algorithm, auth_token_encode};
let key = EncodingKey::from_rsa_pem(include_bytes!("../jwt_rsa.key")).unwrap();
let mut header = Header::new(Algorithm::RS256);
let expiry_timestamp = (Utc::now() + Duration::hours(48)).timestamp();
let claims = Claims {
sub: user.id,
username: user.username.clone(),
exp: expiry_timestamp,
};
let token = auth_token_encode(claims, header, &key).await;
刷新令牌
刷新令牌允许用户登录(获取新的访问令牌),而无需他们输入用户名和密码(完整登录)。
您可以使用 auth_token_encode
和 auth_token_decode
函数创建自己的刷新令牌,或者您可以使用刷新令牌处理器,它应如下所示
use axum_jwt_ware;
let app = Router::new()
.route(
"/refresh",
post(move |body: Json<axum_jwt_ware::RefreshBody>| {
let encoding_context = axum_jwt_ware::EncodingContext {
header: axum_jwt_ware::Header::default(),
validation: axum_jwt_ware::Validation::default(),
key: axum_jwt_ware::EncodingKey::from_secret("refresh_secret".as_ref()),
};
let decoding_context = axum_jwt_ware::DecodingContext {
header: axum_jwt_ware::Header::default(),
validation: axum_jwt_ware::Validation::default(),
key: axum_jwt_ware::DecodingKey::from_secret("refresh_secret".as_ref()),
};
let claims = axum_jwt_ware::Claims {
sub: "jkfajfafghjjfn".to_string(),
username: "ezesunday".to_string(),
exp: (Utc::now() + Duration::hours(48)).timestamp(),
};
axum_jwt_ware::refresh_token(body, encoding_context, decoding_context, Some(claims))
}),
)
更全面的示例
use crate::{
auth,
service::{hello, MyUserData},
};
use axum::{
middleware,
routing::{get, post},
Json, Router,
};
use chrono::{Duration, Utc};
pub fn create_router() -> Router {
let user_data = MyUserData;
let jwt_secret = "secret";
let app = Router::new()
.route(
"/hello",
get(hello)
.layer(middleware::from_fn(move |req, next| {
let key = auth::DecodingKey::from_secret(jwt_secret.as_ref());
let validation = auth::Validation::default();
async move { auth::verify_user(req, &key, validation, next).await }
})),
)
.route(
"/login",
post(move |body: Json<auth::RequestBody>| {
let expiry_timestamp = (Utc::now() + Duration::hours(48)).timestamp();
auth::login(
body,
user_data.clone(),
jwt_secret,
expiry_timestamp.timestamp(),
)
}),
);
app
}
示例
您可以在 GitHub仓库 的示例目录中找到一个工作示例
您已准备好!
特性
- 刷新令牌
- 登录
- 您可以实施自己的登录
- 使用提供的登录
- 身份验证中间件
- 测试
想要贡献?
- 创建问题
- 分叉仓库
- 创建一个修复问题的PR
依赖关系
~6–16MB
~216K SLoC