定义密钥
密钥用于对认证信息进行加密、解密。
const JWT_SECRET: &str = "https://AXUM.RS";
pub struct Keys {
encoding: EncodingKey,
decoding: DecodingKey<'static>,
}
impl Keys {
pub fn new(secret: &[u8]) -> Self {
Self {
encoding: EncodingKey::from_secret(secret),
decoding: DecodingKey::from_secret(secret).into_static(),
}
}
pub fn global() -> Self {
Self::new(JWT_SECRET.as_bytes())
}
}
定义传递的数据
#[derive(Serialize, Deserialize)]
pub struct Claims {
pub sub: String,
pub company: String,
pub exp: usize,
}
定义一些辅助的结构体
请求获取令牌的结构体
#[derive(Deserialize)]
pub struct AuthPayload {
pub client_id: String,
pub client_secret: String,
}
返回给客户端的令牌结构体
#[derive(Serialize)]
pub struct AuthBody {
pub access_token: String,
pub token_type: String,
}
impl AuthBody {
pub fn new(access_token: String) -> Self {
Self {
access_token,
token_type: String::from("Bearer"),
}
}
}
获取授权令牌
async fn authorize(Json(payload): Json<AuthPayload>) -> Result<Json<AuthBody>, Json<String>> {
if payload.client_id.is_empty() || payload.client_secret.is_empty() {
return Err(Json(String::from("Missing Credentials")));
}
if payload.client_id != "axum.rs" || payload.client_secret != "[email protected]" {
return Err(Json(String::from("Wrong Credentials")));
}
let claims = Claims {
sub: "[email protected]".to_string(),
company: "AXUM.RS".to_string(),
exp: 10000000000,
};
let token = encode(&Header::default(), &claims, &Keys::global().encoding)
.map_err(|err| Json(err.to_string()))?;
Ok(Json(AuthBody::new(token)))
}
需要令牌才能访问的资源
async fn protected(
TypedHeader(Authorization(bearer)): TypedHeader<Authorization<Bearer>>,
) -> Result<String, String> {
let token_data = decode::<Claims>(
bearer.token(),
&Keys::global().decoding,
&Validation::default(),
)
.map_err(|err| format!("Invalid Token: {}", err.to_string()))?;
let claims = token_data.claims;
Ok(format!(
"Welcome, your email {}, company: {}",
claims.sub, claims.company
))
}
运行
获取令牌
$ curl -i -X POST -H 'content-type:application/json' -d '{"client_id":"axum.rs","client_secret":"[email protected]"}' http://127.0.0.1:9527/authorize
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZWFtQGF4dW0ucnMiLCJjb21wYW55IjoiQVhVTS5SUyIsImV4cCI6MTAwMDAwMDAwMDB9.2jPYCuK6_nDrFdXS3HLAm43YvbFvrBBLYS6YkZ_z6zM","token_type":"Bearer"}
使用令牌访问被保护的数据
使用非法的令牌访问被保护的数据
curl -H 'content-type:application/json' -H 'Authorization: Bearer foobar' 127.0.0.1:9527/protected
Invalid Token: InvalidSignature
本文讨论了在 axum 集成 JWT 功能,完整代码可以在我们的代码仓库中找到。