aliyun_oss_rust_sdk/
auth.rs

1use base64::Engine;
2use base64::engine::general_purpose;
3use hmac::{Hmac, Mac};
4use reqwest::header::DATE;
5use crate::debug;
6use crate::oss::{API, OSS, OSSInfo};
7use crate::request::{RequestBuilder};
8
9pub trait AuthAPI {
10    fn sign<S: AsRef<str>>(
11        &self,
12        object: S,
13        build: &RequestBuilder,
14    ) -> String;
15
16    fn oss_sign<S: AsRef<str>>(
17        &self,
18        object: S,
19        build: &RequestBuilder,
20    ) -> String;
21}
22
23impl<'a> AuthAPI for OSS {
24    fn sign<S: AsRef<str>>(
25        &self,
26        key: S,
27        build: &RequestBuilder,
28    ) -> String {
29        let date = build
30            .headers
31            .get(&DATE.to_string())
32            .expect("Date header is required");
33        let mut oss_headers = build
34            .oss_headers
35            .iter()
36            .map(|(k, v)| (k.to_lowercase(), v))
37            .collect::<Vec<_>>();
38
39        oss_headers.sort_by(|a, b| a.0.cmp(&b.0));
40
41        let mut canonicalized_oss_headers = oss_headers
42            .iter()
43            .map(|(k, v)| format!("{}:{}", k, v))
44            .collect::<Vec<_>>()
45            .join("\n");
46
47        if oss_headers.len() == 1 {
48            canonicalized_oss_headers = format!("{}\n", canonicalized_oss_headers);
49        }
50
51        let mut canonicalized_resource = self.format_oss_resource_str(self.bucket().as_str(), key.as_ref());
52        if build.parameters.len() > 0 {
53            let mut params = build
54                .parameters
55                .iter()
56                .collect::<Vec<_>>();
57            params.sort_by(|a, b| a.0.cmp(&b.0));
58            canonicalized_resource = format!(
59                "{}?{}",
60                canonicalized_resource,
61                params
62                    .into_iter()
63                    .map(|(k, v)| format!("{}={}", k, v))
64                    .collect::<Vec<_>>()
65                    .join("&")
66            );
67        }
68        let verb = build.method.to_string();
69        let content_md5 = build.content_md5.clone().unwrap_or_default();
70        let content_type = build.content_type.clone().unwrap_or_default();
71        let sign_str = format!(
72            "{}\n{}\n{}\n{}\n{}{}",
73            verb,
74            content_md5,
75            content_type,
76            date,
77            canonicalized_oss_headers,
78            canonicalized_resource,
79        );
80        debug!("oss logsign_str: {}", sign_str);
81        let mut hasher: Hmac<sha1::Sha1> = Hmac::new_from_slice(self.key_secret().as_bytes()).unwrap();
82        hasher.update(sign_str.as_bytes());
83
84        general_purpose::STANDARD.encode(&hasher.finalize().into_bytes())
85    }
86
87    fn oss_sign<S: AsRef<str>>(&self, object: S, build: &RequestBuilder) -> String {
88        let sign_str_base64 = self.sign(object, build);
89        format!("OSS {}:{}", self.key_id(), sign_str_base64)
90    }
91}