sfo_http/
token_helper.rs

1use std::time::Duration;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4pub use jsonwebtoken::*;
5pub use chrono;
6
7pub type TokenResult<T> = errors::Result<T>;
8
9#[derive(Serialize, Deserialize)]
10pub struct Payload<T> {
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub iss: Option<String>, //签发人
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub exp: Option<u64>, //过期时间
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub sub: Option<String>, //主题
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub aud: Option<String>, //受众
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub nbf: Option<u64>, //生效时间
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub iat: Option<u64>, //签发时间
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub jti: Option<u64>, //编号
25    pub data: T,
26}
27
28impl<T> Payload<T> {
29    pub fn is_expire(&self) -> bool {
30        if let Some(exp) = self.exp {
31            let now = Utc::now().timestamp();
32            exp < now as u64
33        } else {
34            false
35        }
36    }
37}
38
39pub struct JsonWebToken;
40
41impl JsonWebToken {
42    pub fn encode<T: Serialize>(alg: Algorithm, data: T, expired_at: DateTime<Utc>, key: &EncodingKey) -> TokenResult<String> {
43        let header = Header::new(alg);
44
45        let payload = Payload {
46            iss: None,
47            exp: Some(expired_at.timestamp() as u64),
48            sub: None,
49            aud: None,
50            nbf: None,
51            iat: None,
52            jti: None,
53            data,
54        };
55        jsonwebtoken::encode(&header, &payload, key)
56    }
57
58    pub fn decode<T: for<'a> Deserialize<'a>>(token: &str, key: &DecodingKey) -> TokenResult<T> {
59        let header = jsonwebtoken::decode_header(token)?;
60        let mut val = Validation::new(header.alg);
61        val.validate_exp = true;
62        let token_data: TokenData<Payload<T>> = jsonwebtoken::decode(token, key, &val)?;
63        Ok(token_data.claims.data)
64    }
65
66    pub fn decode_payload<T: for<'a> Deserialize<'a>>(token: &str, key: &DecodingKey) -> TokenResult<Payload<T>> {
67        let header = jsonwebtoken::decode_header(token)?;
68        let mut val = Validation::new(header.alg);
69        val.validate_exp = true;
70        let token_data: TokenData<Payload<T>> = jsonwebtoken::decode(token, key, &val)?;
71        Ok(token_data.claims)
72    }
73}
74
75pub struct JWTBuilder<T: Serialize> {
76    payload: Payload<T>
77}
78
79impl<T: Serialize> JWTBuilder<T> {
80    pub fn new(data: T) -> Self {
81        Self {
82            payload: Payload {
83                iss: None,
84                exp: None,
85                sub: None,
86                aud: None,
87                nbf: None,
88                iat: None,
89                jti: None,
90                data,
91            }
92        }
93    }
94
95    pub fn iss(mut self, iss: String) -> Self {
96        self.payload.iss = Some(iss);
97        self
98    }
99
100    pub fn exp(mut self, exp: DateTime<Utc>) -> Self {
101        self.payload.exp = Some(exp.timestamp() as u64);
102        self
103    }
104
105    pub fn sub(mut self, sub: String) -> Self {
106        self.payload.sub = Some(sub);
107        self
108    }
109
110    pub fn aud(mut self, aud: String) -> Self {
111        self.payload.aud = Some(aud);
112        self
113    }
114
115    pub fn nbf(mut self, nbf: DateTime<Utc>) -> Self {
116        self.payload.nbf = Some(nbf.timestamp() as u64);
117        self
118    }
119
120    pub fn iat(mut self, iat: DateTime<Utc>) -> Self {
121        self.payload.iat = Some(iat.timestamp() as u64);
122        self
123    }
124
125    pub fn jti(mut self, jti: u64) -> Self {
126        self.payload.jti = Some(jti);
127        self
128    }
129
130    pub fn build(self, alg: Algorithm, key: &EncodingKey) -> TokenResult<String> {
131        let header = Header::new(alg);
132        jsonwebtoken::encode(&header, &self.payload, key)
133    }
134}