#authorization-header #rocket-web #authorization #rocket #header #web-server #parse

rocket-authorization

为Rocket.rs Web服务器提供一个库,以方便地访问和解析请求中的授权头

2个版本 (1个稳定版)

1.0.0 2023年11月5日
0.2.0-rc.12021年11月23日

HTTP服务器 中排名 633

Download history 108/week @ 2024-04-22 104/week @ 2024-04-29 112/week @ 2024-05-06 46/week @ 2024-05-13 23/week @ 2024-05-20 53/week @ 2024-05-27 141/week @ 2024-06-03 73/week @ 2024-06-10 134/week @ 2024-06-17 86/week @ 2024-06-24 89/week @ 2024-07-01 186/week @ 2024-07-08 165/week @ 2024-07-15 147/week @ 2024-07-22 122/week @ 2024-07-29 179/week @ 2024-08-05

每月下载量 616

MIT/Apache

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