2 个版本
0.1.1 | 2022 年 7 月 9 日 |
---|---|
0.1.0 | 2022 年 7 月 9 日 |
每月 119 次下载
10KB
82 行
tide-jwt
tide-jwt 是 tide 网页框架的 JWT 授权中间件的简单实现。它使用 jsonwebtoken crate 进行编码/解码。如果发现存在无效的 "Authorization" 头部,它将只返回未授权。如果没有找到授权头部,中间件将继续运行。确保请求确实经过认证是实施者的责任,以防止下游中间件运行并返回适当的响应。
特性
[x] 读取 "Authorization" 头部 [x] 使用泛型声明和 jsonwebtoken 验证 "Bearer" 令牌 [x] 提供编码辅助函数(从密钥 base64、选择的算法、声明) [x] 支持 Send + Sync + 'static, 可序列化和反序列化 (serde) 声明,用于 jsonwebtoken [] 可能读取配置的 jwt 令牌 [x] 支持非 jwt (jose 规范)
示例
使用 tide 网页框架的实现非常简单,只需使用 .with
函数包含中间件即可。这在技术上相当于一个 Before 中间件,它在继续其他中间件之前从 Request 中读取。它将使用 set_ext 函数添加获取 <Claims>
对象的能力,并将其作为扩展添加到请求上。
use jsonwebtoken::{DecodingKey, Validation};
use registry::State;
use serde::{Deserialize, Serialize};
use tide::log::LogMiddleware;
use tide_jwt::JwtAuthenticationDecoder;
mod flash;
mod registry;
mod routes;
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
sub: String,
username: String,
uid: u64,
exp: usize,
}
#[async_std::main]
async fn main() -> tide::Result<()> {
let mut app = tide::with_state(State::new());
dotenv::dotenv().ok();
env_logger::init();
app.with(LogMiddleware::new());
// configure openid connect and session middleware
let jwt_secret = std::env::var("SESSION_SECRET")?;
app.with(JwtAuthenticationDecoder::<Claims>::new(
Validation::default(),
DecodingKey::from_base64_secret(&jwt_secret)?,
));
routes::configure(&mut app);
let host = std::env::var("HOST").unwrap_or(String::from("0.0.0.0"));
let port: u16 = std::env::var("PORT")?.parse()?;
app.listen((host, port)).await?;
Ok(())
}
上面的示例将允许中间件正确解码请求中的 Claims 并将其作为扩展设置在请求上。这使得我们可以在端点或其他中间件函数中稍后抓取它。
pub async fn index(req: Request<State>) -> tide::Result {
let claims = req.ext::<Claims>();
println!("{:?}", claims);
let mut res = Response::new(200);
Ok(res)
}
假设您已正确认证了请求,您可以使用 encode
实用函数来编码带有正确声明的令牌。
pub async fn login(mut req: Request<State>) -> tide::Result {
match req.body_form::<UserForm>().await {
Ok(form) => {
if form.username == "foo" && form.password == "bar" {
let mut res: Response = Redirect::new("/").into();
let secret = std::env::var("SESSION_SECRET")?;
let claims = Claims {
username: String::from("foo"),
exp: 10000000000,
sub: String::from("asdf"),
uid: 1,
};
let token = tide_jwt::jwtsign_secret(&claims, &secret)?;
println!("{token}");
res.insert_cookie(
Cookie::build("_jwt", token)
.max_age(Duration::seconds(60000))
.same_site(SameSite::Lax)
.path("/")
.finish(),
);
Ok(res)
} else {
flash::redirect("/", flash::warn("invalid credentials"))
}
}
Err(e) => flash::redirect("/", flash::error(e.to_string().as_str())),
}
}
声明应该构建为允许某些唯一性(例如 exp 或 iat),以便每次执行加密/签名时都具有唯一性。需要注意的是,通常使用会话进行 Web 应用的认证,而 JWT 通常保留用于后端 api 服务(或者如果您正在考虑无服务器类型的生产系统)。
依赖关系
~15–27MB
~525K SLoC