aliyun_oss_rust_sdk/
auth.rs1use 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}