|
|
@@ -19,13 +19,13 @@ class AuthRepository {
|
|
19
|
19
|
required SharedPreferences prefs,
|
|
20
|
20
|
}) : _apiClient = apiClient, _prefs = prefs;
|
|
21
|
21
|
|
|
22
|
|
- // 登录(需要使用安全登录替代)
|
|
|
22
|
+ // 登录(需要使用安全登录替代)保存双token
|
|
23
|
23
|
Future<ApiResponse<User>> login(LoginRequest request) async {
|
|
24
|
24
|
try {
|
|
25
|
25
|
final response = await _apiClient.post(
|
|
26
|
26
|
ApiConstants.getLoginUrl(),
|
|
27
|
27
|
request.toJson(),
|
|
28
|
|
- withAuth: false,
|
|
|
28
|
+ withAuth: false, // 登录不需要认证头
|
|
29
|
29
|
);
|
|
30
|
30
|
|
|
31
|
31
|
if (response.statusCode == 200) {
|
|
|
@@ -33,8 +33,17 @@ class AuthRepository {
|
|
33
|
33
|
json.decode(response.body)
|
|
34
|
34
|
);
|
|
35
|
35
|
|
|
36
|
|
- // 保存token
|
|
37
|
|
- await _apiClient.saveToken(tokenResponse.accessToken);
|
|
|
36
|
+ // 保存access_token和refresh_token
|
|
|
37
|
+ await _apiClient.saveTokens(
|
|
|
38
|
+ tokenResponse.accessToken,
|
|
|
39
|
+ tokenResponse.refreshToken,
|
|
|
40
|
+ );
|
|
|
41
|
+
|
|
|
42
|
+ // 保存用户数据
|
|
|
43
|
+ await _prefs.setString(
|
|
|
44
|
+ 'user_data',
|
|
|
45
|
+ json.encode(tokenResponse.user.toJson()),
|
|
|
46
|
+ );
|
|
38
|
47
|
|
|
39
|
48
|
return ApiResponse<User>(
|
|
40
|
49
|
success: true,
|
|
|
@@ -56,7 +65,7 @@ class AuthRepository {
|
|
56
|
65
|
}
|
|
57
|
66
|
}
|
|
58
|
67
|
|
|
59
|
|
- // 注册(需要使用安全注册替代)
|
|
|
68
|
+ // 注册(需要使用安全注册替代)保存双token
|
|
60
|
69
|
Future<ApiResponse<User>> register(RegisterRequest request) async {
|
|
61
|
70
|
try {
|
|
62
|
71
|
final response = await _apiClient.post(
|
|
|
@@ -70,8 +79,17 @@ class AuthRepository {
|
|
70
|
79
|
json.decode(response.body)
|
|
71
|
80
|
);
|
|
72
|
81
|
|
|
73
|
|
- // 保存token
|
|
74
|
|
- await _apiClient.saveToken(tokenResponse.accessToken);
|
|
|
82
|
+ // 保存双token
|
|
|
83
|
+ await _apiClient.saveTokens(
|
|
|
84
|
+ tokenResponse.accessToken,
|
|
|
85
|
+ tokenResponse.refreshToken,
|
|
|
86
|
+ );
|
|
|
87
|
+
|
|
|
88
|
+ // 保存用户数据
|
|
|
89
|
+ await _prefs.setString(
|
|
|
90
|
+ 'user_data',
|
|
|
91
|
+ json.encode(tokenResponse.user.toJson()),
|
|
|
92
|
+ );
|
|
75
|
93
|
|
|
76
|
94
|
return ApiResponse<User>(
|
|
77
|
95
|
success: true,
|
|
|
@@ -101,16 +119,12 @@ class AuthRepository {
|
|
101
|
119
|
username: request.username,
|
|
102
|
120
|
password: request.password,
|
|
103
|
121
|
);
|
|
104
|
|
-
|
|
105
|
|
- print(ApiConstants.getLoginUrl());
|
|
106
|
|
- print(secureRequest.toJson());
|
|
107
|
122
|
|
|
108
|
123
|
final response = await _apiClient.post(
|
|
109
|
124
|
ApiConstants.getLoginUrl(),
|
|
110
|
125
|
secureRequest.toJson(),
|
|
111
|
126
|
withAuth: false,
|
|
112
|
127
|
);
|
|
113
|
|
- print(response.statusCode);
|
|
114
|
128
|
|
|
115
|
129
|
// ... 处理响应
|
|
116
|
130
|
if (response.statusCode == 200) {
|
|
|
@@ -118,8 +132,17 @@ class AuthRepository {
|
|
118
|
132
|
json.decode(response.body)
|
|
119
|
133
|
);
|
|
120
|
134
|
|
|
121
|
|
- // 保存token
|
|
122
|
|
- await _apiClient.saveToken(tokenResponse.accessToken);
|
|
|
135
|
+ // 保存access_token和refresh_token
|
|
|
136
|
+ await _apiClient.saveTokens(
|
|
|
137
|
+ tokenResponse.accessToken,
|
|
|
138
|
+ tokenResponse.refreshToken,
|
|
|
139
|
+ );
|
|
|
140
|
+
|
|
|
141
|
+ // 保存用户数据
|
|
|
142
|
+ await _prefs.setString(
|
|
|
143
|
+ 'user_data',
|
|
|
144
|
+ json.encode(tokenResponse.user.toJson()),
|
|
|
145
|
+ );
|
|
123
|
146
|
|
|
124
|
147
|
return ApiResponse<User>(
|
|
125
|
148
|
success: true,
|
|
|
@@ -169,8 +192,17 @@ class AuthRepository {
|
|
169
|
192
|
json.decode(response.body)
|
|
170
|
193
|
);
|
|
171
|
194
|
|
|
172
|
|
- // 保存token
|
|
173
|
|
- await _apiClient.saveToken(tokenResponse.accessToken);
|
|
|
195
|
+ // 保存双token
|
|
|
196
|
+ await _apiClient.saveTokens(
|
|
|
197
|
+ tokenResponse.accessToken,
|
|
|
198
|
+ tokenResponse.refreshToken,
|
|
|
199
|
+ );
|
|
|
200
|
+
|
|
|
201
|
+ // 保存用户数据
|
|
|
202
|
+ await _prefs.setString(
|
|
|
203
|
+ 'user_data',
|
|
|
204
|
+ json.encode(tokenResponse.user.toJson()),
|
|
|
205
|
+ );
|
|
174
|
206
|
|
|
175
|
207
|
return ApiResponse<User>(
|
|
176
|
208
|
success: true,
|
|
|
@@ -202,11 +234,28 @@ class AuthRepository {
|
|
202
|
234
|
|
|
203
|
235
|
if (response.statusCode == 200) {
|
|
204
|
236
|
final userData = json.decode(response.body);
|
|
|
237
|
+ final user = User.fromJson(userData);
|
|
|
238
|
+
|
|
|
239
|
+ // 更新本地用户数据
|
|
|
240
|
+ await _prefs.setString('user_data', json.encode(user.toJson()));
|
|
|
241
|
+
|
|
205
|
242
|
return ApiResponse<User>(
|
|
206
|
243
|
success: true,
|
|
207
|
244
|
message: '获取成功',
|
|
208
|
|
- data: User.fromJson(userData),
|
|
|
245
|
+ data: user,
|
|
209
|
246
|
);
|
|
|
247
|
+ } else if (response.statusCode == 401) {
|
|
|
248
|
+ // Token过期,尝试刷新
|
|
|
249
|
+ final refreshResult = await _refreshToken();
|
|
|
250
|
+ if (refreshResult) {
|
|
|
251
|
+ // 刷新成功,重新获取用户信息
|
|
|
252
|
+ return await getCurrentUser();
|
|
|
253
|
+ } else {
|
|
|
254
|
+ return ApiResponse<User>(
|
|
|
255
|
+ success: false,
|
|
|
256
|
+ message: '登录已过期,请重新登录',
|
|
|
257
|
+ );
|
|
|
258
|
+ }
|
|
210
|
259
|
} else {
|
|
211
|
260
|
return ApiResponse<User>(
|
|
212
|
261
|
success: false,
|
|
|
@@ -220,28 +269,111 @@ class AuthRepository {
|
|
220
|
269
|
);
|
|
221
|
270
|
}
|
|
222
|
271
|
}
|
|
223
|
|
-
|
|
224
|
|
- // 登出
|
|
225
|
|
- Future<bool> logout() async {
|
|
|
272
|
+
|
|
|
273
|
+ // 刷新Token
|
|
|
274
|
+ Future<bool> _refreshToken() async {
|
|
226
|
275
|
try {
|
|
|
276
|
+ final refreshToken = _apiClient.getRefreshToken();
|
|
|
277
|
+
|
|
|
278
|
+ if (refreshToken == null || refreshToken.isEmpty) {
|
|
|
279
|
+ return false;
|
|
|
280
|
+ }
|
|
|
281
|
+
|
|
227
|
282
|
final response = await _apiClient.post(
|
|
228
|
|
- ApiConstants.getLogoutUrl(),
|
|
229
|
|
- {},
|
|
230
|
|
- withAuth: true,
|
|
|
283
|
+ ApiConstants.getRefreshUrl(), // 需要添加这个常量
|
|
|
284
|
+ {'refresh_token': refreshToken},
|
|
|
285
|
+ withAuth: false,
|
|
231
|
286
|
);
|
|
232
|
287
|
|
|
233
|
288
|
if (response.statusCode == 200) {
|
|
234
|
|
- await _apiClient.clearToken();
|
|
|
289
|
+ final data = json.decode(response.body);
|
|
|
290
|
+ final newAccessToken = data['access_token'];
|
|
|
291
|
+ final newRefreshToken = data['refresh_token'];
|
|
|
292
|
+
|
|
|
293
|
+ // 保存新的tokens
|
|
|
294
|
+ await _apiClient.saveTokens(newAccessToken, newRefreshToken);
|
|
235
|
295
|
return true;
|
|
236
|
296
|
}
|
|
|
297
|
+
|
|
237
|
298
|
return false;
|
|
238
|
299
|
} catch (e) {
|
|
239
|
300
|
return false;
|
|
240
|
301
|
}
|
|
241
|
302
|
}
|
|
242
|
303
|
|
|
|
304
|
+ // 登出
|
|
|
305
|
+ Future<ApiResponse<bool>> logout() async {
|
|
|
306
|
+ try {
|
|
|
307
|
+ // 获取refresh_token
|
|
|
308
|
+ final refreshToken = _apiClient.getRefreshToken();
|
|
|
309
|
+
|
|
|
310
|
+ if (refreshToken == null || refreshToken.isEmpty) {
|
|
|
311
|
+ // 没有refresh_token,只清除本地数据
|
|
|
312
|
+ await _clearLocalData();
|
|
|
313
|
+ return ApiResponse<bool>(
|
|
|
314
|
+ success: true,
|
|
|
315
|
+ message: '已退出登录',
|
|
|
316
|
+ data: true,
|
|
|
317
|
+ );
|
|
|
318
|
+ }
|
|
|
319
|
+
|
|
|
320
|
+ // 发送登出请求到服务器
|
|
|
321
|
+ final response = await _apiClient.post(
|
|
|
322
|
+ ApiConstants.getLogoutUrl(),
|
|
|
323
|
+ {'refresh_token': refreshToken},
|
|
|
324
|
+ withAuth: true, // 需要access_token认证头
|
|
|
325
|
+ );
|
|
|
326
|
+
|
|
|
327
|
+ // 无论服务器响应如何,都清除本地数据
|
|
|
328
|
+ await _clearLocalData();
|
|
|
329
|
+
|
|
|
330
|
+ if (response.statusCode == 200) {
|
|
|
331
|
+ return ApiResponse<bool>(
|
|
|
332
|
+ success: true,
|
|
|
333
|
+ message: '已成功退出登录',
|
|
|
334
|
+ data: true,
|
|
|
335
|
+ );
|
|
|
336
|
+ } else {
|
|
|
337
|
+ // 服务器登出失败,但本地已清除
|
|
|
338
|
+ return ApiResponse<bool>(
|
|
|
339
|
+ success: true,
|
|
|
340
|
+ message: '已退出登录(服务器通信失败)',
|
|
|
341
|
+ data: true,
|
|
|
342
|
+ );
|
|
|
343
|
+ }
|
|
|
344
|
+ } catch (e) {
|
|
|
345
|
+ // 网络异常,仍然清除本地数据
|
|
|
346
|
+ await _clearLocalData();
|
|
|
347
|
+ return ApiResponse<bool>(
|
|
|
348
|
+ success: true,
|
|
|
349
|
+ message: '已退出登录(网络异常)',
|
|
|
350
|
+ data: true,
|
|
|
351
|
+ );
|
|
|
352
|
+ }
|
|
|
353
|
+ }
|
|
|
354
|
+
|
|
|
355
|
+ // 清除本地数据
|
|
|
356
|
+ Future<void> _clearLocalData() async {
|
|
|
357
|
+ await _apiClient.clearTokens();
|
|
|
358
|
+ await _prefs.remove('user_data');
|
|
|
359
|
+ }
|
|
|
360
|
+
|
|
243
|
361
|
// 检查登录状态
|
|
244
|
362
|
Future<bool> isLoggedIn() async {
|
|
245
|
|
- return _apiClient.isLoggedIn();
|
|
|
363
|
+ // 检查是否有access_token
|
|
|
364
|
+ if (!_apiClient.isLoggedIn()) {
|
|
|
365
|
+ return false;
|
|
|
366
|
+ }
|
|
|
367
|
+
|
|
|
368
|
+ // 可以进一步验证token是否有效
|
|
|
369
|
+ try {
|
|
|
370
|
+ final response = await _apiClient.get(
|
|
|
371
|
+ ApiConstants.getCurrentUserUrl(),
|
|
|
372
|
+ withAuth: true,
|
|
|
373
|
+ );
|
|
|
374
|
+ return response.statusCode == 200;
|
|
|
375
|
+ } catch (e) {
|
|
|
376
|
+ return false;
|
|
|
377
|
+ }
|
|
246
|
378
|
}
|
|
247
|
379
|
}
|