2个版本 (1个稳定版)
1.0.0 | 2023年11月5日 |
---|---|
0.2.0-rc.1 | 2021年11月23日 |
在 HTTP服务器 中排名 633
每月下载量 616
16KB
160 行
Rocket.rs 的授权解析
这是一个库,用于Rocket Web服务器,可以轻松访问和解析请求中的 Authorization
头,以请求保护的形式。该库不提供执行身份验证或生成有效登录令牌的功能。
最常见的用例是在已经发生身份验证的其他地方的Web微服务中,微服务只需要使用和验证已生成的授权凭据。
请查看 example
目录中的源代码,直到添加了适当的文档。
API文档可以在 docs.rs 上找到。
安装
要使用此crate,运行 cargo add rocket-authorization
,或将以下内容手动添加到您的 Cargo.toml
文件中
[dependencies]
rocket-authorization = "1.0.0"
使用
提取基本身份验证头的用户名和密码
use rocket::get;
use rocket_authorization::basic::Basic;
use rocket_authorization::{AuthError, Credential};
#[get("/auth/basic_only")]
async fn auth_basic_only(auth: Credential<Basic>) -> String {
// This function only executes with valid basic authentication credentials.
// Note that the `Basic` type extracts a username and password,
// but you still need to do your own password validation.
let user = user.fetch(auth.username, auth.password).await?;
format!("Hello {}!", user.name)
}
#[get("/auth/basic_maybe")]
async fn auth_basic_maybe(auth: Result<Credential<Basic>, AuthError>) -> String {
match auth {
Ok(credential) => {
let user = user.fetch(auth.username, auth.password).await?;
format!("Hello {}!", user.name)
},
Err(error) => {
// Since we extract a `Result<Credential<_>, AuthError>`,
// we can have custom handling of not being authenticated.
format!("Error {error}!")
}
}
}
# Executes route handler.
curl localhost:8000/auth/basic_only -u username:password
# Executes `Ok` case of route handler.
curl localhost:8000/auth/basic_maybe -u username:password
# Executes `Err` case of route handler.
curl localhost:8000/auth/basic_maybe
提取OAuth身份验证头的bearer令牌
use rocket::get;
use rocket_authorization::oauth::OAuth;
use rocket_authorization::{AuthError, Credential};
#[get("/auth/bearer_only")]
async fn auth_bearer_only(auth: Credential<OAuth>) -> String {
// This function only executes with valid OAuth bearer authentication token.
// Note that the `OAuth` type extracts a bearer token,
// but you still need to do your own password validation.
let user = user.fetch(auth.token).await?;
format!("Hello {}!", user.name)
}
#[get("/auth/bearer_maybe")]
async fn auth_bearer_maybe(auth: Result<Credential<OAuth>, AuthError>) -> String {
match auth {
Ok(credential) => {
let user = user.fetch(credential.token).await?;
format!("Hello {}!", user.name)
},
Err(error) => {
// Since we extract a `Result<Credential<_>, AuthError>`,
// we can have custom handling of not being authenticated.
format!("Error {error}!")
}
}
}
# Executes route handler.
curl localhost:8000/auth/bearer_only -H 'Authorization: Bearer SomeTokenHere'
# Executes `Ok` case of route handler.
curl localhost:8000/auth/bearer_maybe -H 'Authorization: Bearer SomeTokenHere'
# Executes `Err` case of route handler.
curl localhost:8000/auth/bearer_maybe
提取自定义身份验证头
use rocket::get;
use rocket_authorization::{AuthError, Authorization, Request};
#[derive(Debug)]
pub struct CustomAuth {
pub slug: String,
pub token: String,
}
#[rocket::async_trait]
impl Authorization for CustomAuth {
const KIND: &'static str = "Custom";
async fn parse(_: &str, credential: &str, request: &Request) -> Result<Self, AuthError> {
let components: Vec<_> = credential.split(":").collect();
if components.len() != 2 {
return Err(AuthError::Unprocessable(
"Invalid Key-Value Pair Format Error".into(),
));
}
let (slug, token) = (components[0].trim(), components[1].trim());
if slug.is_empty() || token.is_empty() {
return Err(AuthError::HeaderMissing);
}
Ok(CustomAuth {
slug: slug.into(),
token: token.into(),
})
}
}
#[get("/auth/custom_only")]
async fn auth_custom_only(auth: Credential<CustomAuth>) -> String {
// This function only executes with valid authentication value.
let user = user.fetch(auth.token, auth.slug).await?;
format!("Hello {}!", user.name)
}
#[get("/auth/custom_maybe")]
async fn auth_custom_maybe(auth: Result<Credential<CustomAuth>, AuthError>) -> String {
match auth {
Ok(credential) => {
let user = user.fetch(auth.token, auth.slug).await?;
format!("Hello {}!", user.name)
},
Err(error) => {
// Since we extract a `Result<Credential<_>, AuthError>`,
// we can have custom handling of not being authenticated.
format!("Error {error}!")
}
}
}
# Executes route handler.
curl localhost:8000/auth/custom_only -H 'Authorization: Custom SomeTokenHere:SomeSlugHere'
# Executes `Ok` case of route handler.
curl localhost:8000/auth/custom_maybe -H 'Authorization: Custom SomeTokenHere:SomeSlugHere'
# Executes `Err` case of route handler.
curl localhost:8000/auth/custom_maybe
从其他请求提取器中提取身份验证头
凭据可以从任何具有 Request
值访问的地方解析出来,这使得为路由编写定制的身份验证保护变得容易。
use super::{Basic, Credential};
use rocket::{http::Status, request::FromRequest, request::Outcome, Request};
#[derive(Debug)]
pub struct SysAdmin(pub String);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for SysAdmin {
type Error = ();
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let provided_auth = match Credential::<Basic>::from_request(request).await {
Outcome::Success(auth) => auth,
Outcome::Error(error) => return Outcome::Error((error.0, ())),
Outcome::Forward(status) => return Outcome::Forward(status),
};
// THIS IS FOR DEMONSTRATION PURPOSES ONLY, THIS IS NOT SECURE USAGE!
// This would be the place where a database lookup might be performed.
if provided_auth.username == "root" && provided_auth.password == "p2ssw0rd" {
Outcome::Success(SysAdmin(provided_auth.into_inner().username))
} else {
Outcome::Error((Status::Unauthorized, ()))
}
}
}
#[get("/secure/sysadmin")]
fn secure_sysadmin(user: SysAdmin) -> String {
// This function only executes with valid authentication value.
format!("Hello {}!", user.0)
}
# Executes route handler.
curl localhost:8000/secure/sysadmin -u root:p2ssw0rd
# Responds with 401 Unauthorized and never executes route handler.
curl localhost:8000/secure/sysadmin -u some:other
# Responds with 401 Unauthorized and never executes route handler.
curl localhost:8000/auth/custom_maybe
依赖关系
约15-46MB
~784K SLoC