forked from sa-tokens/sa-token-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoauth2_example.rs
More file actions
161 lines (131 loc) · 5.52 KB
/
Copy pathoauth2_example.rs
File metadata and controls
161 lines (131 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! OAuth2 授权码模式示例
//!
//! 演示完整的 OAuth2 授权流程
//!
//! ## 导入方式
//!
//! ### 方式1: 独立使用核心库(本示例)
//! ```ignore
//! use sa_token_core::{OAuth2Manager, OAuth2Client};
//! ```
//!
//! ### 方式2: 使用 Web 框架插件(推荐)
//! ```toml
//! [dependencies]
//! sa-token-plugin-axum = "0.1.3"
//! ```
//! ```ignore
//! use sa_token_plugin_axum::*; // OAuth2 相关类型已重新导出!
//! ```
use std::sync::Arc;
use sa_token_core::{OAuth2Manager, OAuth2Client};
use sa_token_storage_memory::MemoryStorage;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("========================================");
println!("OAuth2 授权码模式示例 | OAuth2 Authorization Code Flow Example");
println!("========================================\n");
let storage = Arc::new(MemoryStorage::new());
let oauth2 = OAuth2Manager::new(storage)
.with_ttl(600, 3600, 2592000);
println!(">>> 步骤 1: 注册 OAuth2 客户端 | Step 1: Register OAuth2 Client\n");
let client = OAuth2Client {
client_id: "web_app_001".to_string(),
client_secret: "secret_abc123xyz".to_string(),
redirect_uris: vec![
"http://localhost:3000/callback".to_string(),
"http://localhost:3000/auth/callback".to_string(),
],
grant_types: vec![
"authorization_code".to_string(),
"refresh_token".to_string(),
],
scope: vec![
"read".to_string(),
"write".to_string(),
"profile".to_string(),
],
};
oauth2.register_client(&client).await?;
println!("客户端信息:");
println!(" Client ID: {}", client.client_id);
println!(" Client Secret: {}", client.client_secret);
println!(" Redirect URIs: {:?}", client.redirect_uris);
println!(" Grant Types: {:?}", client.grant_types);
println!(" Scopes: {:?}\n", client.scope);
println!(">>> 步骤 2: 用户授权 - 生成授权码\n");
let user_id = "user_10086";
let redirect_uri = "http://localhost:3000/callback";
let requested_scope = vec!["read".to_string(), "profile".to_string()];
if !oauth2.validate_redirect_uri(&client, redirect_uri) {
return Err("Invalid redirect URI".into());
}
if !oauth2.validate_scope(&client, &requested_scope) {
return Err("Invalid scope".into());
}
let auth_code = oauth2.generate_authorization_code(
client.client_id.clone(),
user_id.to_string(),
redirect_uri.to_string(),
requested_scope.clone(),
);
println!("授权码信息:");
println!(" Code: {}", auth_code.code);
println!(" User ID: {}", auth_code.user_id);
println!(" Client ID: {}", auth_code.client_id);
println!(" Redirect URI: {}", auth_code.redirect_uri);
println!(" Scope: {:?}", auth_code.scope);
println!(" Expires At: {}\n", auth_code.expires_at);
oauth2.store_authorization_code(&auth_code).await?;
println!("✓ 授权码已存储\n");
println!(">>> 步骤 3: 用授权码换取访问令牌\n");
let access_token = oauth2.exchange_code_for_token(
&auth_code.code,
&client.client_id,
&client.client_secret,
redirect_uri,
).await?;
println!("访问令牌:");
println!(" Access Token: {}", access_token.access_token);
println!(" Token Type: {}", access_token.token_type);
println!(" Expires In: {} 秒", access_token.expires_in);
println!(" Refresh Token: {}", access_token.refresh_token.as_ref().unwrap());
println!(" Scope: {:?}\n", access_token.scope);
println!(">>> 步骤 4: 验证访问令牌\n");
let token_info = oauth2.verify_access_token(&access_token.access_token).await?;
println!("令牌信息:");
println!(" User ID: {}", token_info.user_id);
println!(" Client ID: {}", token_info.client_id);
println!(" Scope: {:?}", token_info.scope);
println!(" Expires At: {}\n", token_info.expires_at);
println!(">>> 步骤 5: 使用刷新令牌获取新的访问令牌\n");
let refresh_token = access_token.refresh_token.as_ref().unwrap();
let new_access_token = oauth2.refresh_access_token(
refresh_token,
&client.client_id,
&client.client_secret,
).await?;
println!("新访问令牌:");
println!(" Access Token: {}", new_access_token.access_token);
println!(" Token Type: {}", new_access_token.token_type);
println!(" Expires In: {} 秒", new_access_token.expires_in);
println!(" Refresh Token: {}\n", new_access_token.refresh_token.as_ref().unwrap());
println!(">>> 步骤 6: 撤销令牌\n");
oauth2.revoke_token(&new_access_token.access_token).await?;
println!("✓ 令牌已撤销\n");
match oauth2.verify_access_token(&new_access_token.access_token).await {
Ok(_) => println!("✗ 令牌仍然有效(不应该)"),
Err(_) => println!("✓ 令牌已失效(预期结果)\n"),
}
println!("========================================");
println!("OAuth2 授权流程完成");
println!("========================================\n");
println!("完整流程:");
println!(" 1. 注册客户端 ✓");
println!(" 2. 生成授权码 ✓");
println!(" 3. 授权码换令牌 ✓");
println!(" 4. 验证访问令牌 ✓");
println!(" 5. 刷新访问令牌 ✓");
println!(" 6. 撤销令牌 ✓");
Ok(())
}