| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- import 'dart:convert';
- import 'package:shared_preferences/shared_preferences.dart';
- import '../../core/constants/api_constants.dart';
- import '../../core/utils/crypto_utils.dart';
- import '../datasources/remote/api_client.dart';
- import '../models/auth/secure_login_request.dart';
- import '../models/user.dart';
- import '../models/auth/login_request.dart';
- import '../models/auth/register_request.dart';
- import '../models/auth/token_response.dart';
- import '../models/api_response.dart';
-
- class AuthRepository {
- final ApiClient _apiClient;
- final SharedPreferences _prefs;
-
- AuthRepository({
- required ApiClient apiClient,
- required SharedPreferences prefs,
- }) : _apiClient = apiClient, _prefs = prefs;
-
- // 登录(需要使用安全登录替代)保存双token
- Future<ApiResponse<User>> login(LoginRequest request) async {
- try {
- final response = await _apiClient.post(
- ApiConstants.getLoginUrl(),
- request.toJson(),
- withAuth: false, // 登录不需要认证头
- );
-
- if (response.statusCode == 200) {
- final tokenResponse = TokenResponse.fromJson(
- json.decode(response.body)
- );
-
- // 保存access_token和refresh_token
- await _apiClient.saveTokens(
- tokenResponse.accessToken,
- tokenResponse.refreshToken,
- );
-
- // 保存用户数据
- await _prefs.setString(
- 'user_data',
- json.encode(tokenResponse.user.toJson()),
- );
-
- return ApiResponse<User>(
- success: true,
- message: '登录成功',
- data: tokenResponse.user,
- );
- } else {
- final error = json.decode(response.body);
- return ApiResponse<User>(
- success: false,
- message: error['detail'] ?? '登录失败',
- );
- }
- } catch (e) {
- return ApiResponse<User>(
- success: false,
- message: '登录失败: $e',
- );
- }
- }
-
- // 注册(需要使用安全注册替代)保存双token
- Future<ApiResponse<User>> register(RegisterRequest request) async {
- try {
- final response = await _apiClient.post(
- ApiConstants.getRegisterUrl(),
- request.toJson(),
- withAuth: false,
- );
-
- if (response.statusCode == 201) {
- final tokenResponse = TokenResponse.fromJson(
- json.decode(response.body)
- );
-
- // 保存双token
- await _apiClient.saveTokens(
- tokenResponse.accessToken,
- tokenResponse.refreshToken,
- );
-
- // 保存用户数据
- await _prefs.setString(
- 'user_data',
- json.encode(tokenResponse.user.toJson()),
- );
-
- return ApiResponse<User>(
- success: true,
- message: '注册成功',
- data: tokenResponse.user,
- );
- } else {
- final error = json.decode(response.body);
- return ApiResponse<User>(
- success: false,
- message: error['detail'] ?? '注册失败',
- );
- }
- } catch (e) {
- return ApiResponse<User>(
- success: false,
- message: '注册失败: $e',
- );
- }
- }
-
- // 安全登录方法
- Future<ApiResponse<User>> secureLogin(LoginRequest request) async {
- try {
- // 创建安全登录请求
- final secureRequest = SecureLoginRequest.create(
- username: request.username,
- password: request.password,
- );
-
- final response = await _apiClient.post(
- ApiConstants.getLoginUrl(),
- secureRequest.toJson(),
- withAuth: false,
- );
-
- // ... 处理响应
- if (response.statusCode == 200) {
- final tokenResponse = TokenResponse.fromJson(
- json.decode(response.body)
- );
-
- // 保存access_token和refresh_token
- await _apiClient.saveTokens(
- tokenResponse.accessToken,
- tokenResponse.refreshToken,
- );
-
- // 保存用户数据
- await _prefs.setString(
- 'user_data',
- json.encode(tokenResponse.user.toJson()),
- );
-
- return ApiResponse<User>(
- success: true,
- message: '登录成功',
- data: tokenResponse.user,
- );
- } else {
- final error = json.decode(response.body);
- return ApiResponse<User>(
- success: false,
- message: error['detail'] ?? '登录失败',
- );
- }
- } catch (e) {
- return ApiResponse<User>(
- success: false,
- message: '登录失败: $e',
- );
- }
- }
-
- // 安全注册方法
- Future<ApiResponse<User>> secureRegister(RegisterRequest request) async {
- try {
- // 创建安全注册数据
- final salt = CryptoUtils.generateSalt();
- final passwordHash = CryptoUtils.sha256Hash(request.password + salt);
-
- final registerData = {
- 'username': request.username,
- 'email': request.email,
- 'password_hash': passwordHash,
- 'salt': salt,
- 'full_name': request.fullName,
- 'password_confirm': request.passwordConfirm,
- };
-
- final response = await _apiClient.post(
- ApiConstants.getRegisterUrl(),
- registerData,
- withAuth: false,
- );
-
- // ... 处理响应
- if (response.statusCode == 201) {
- final tokenResponse = TokenResponse.fromJson(
- json.decode(response.body)
- );
-
- // 保存双token
- await _apiClient.saveTokens(
- tokenResponse.accessToken,
- tokenResponse.refreshToken,
- );
-
- // 保存用户数据
- await _prefs.setString(
- 'user_data',
- json.encode(tokenResponse.user.toJson()),
- );
-
- return ApiResponse<User>(
- success: true,
- message: '注册成功',
- data: tokenResponse.user,
- );
- } else {
- final error = json.decode(response.body);
- return ApiResponse<User>(
- success: false,
- message: error['detail'] ?? '注册失败',
- );
- }
- } catch (e) {
- return ApiResponse<User>(
- success: false,
- message: '注册失败: $e',
- );
- }
- }
-
- // 获取当前用户
- Future<ApiResponse<User>> getCurrentUser() async {
- try {
- final response = await _apiClient.get(
- ApiConstants.getCurrentUserUrl(),
- withAuth: true,
- );
-
- if (response.statusCode == 200) {
- final userData = json.decode(response.body);
- final user = User.fromJson(userData);
-
- // 更新本地用户数据
- await _prefs.setString('user_data', json.encode(user.toJson()));
-
- return ApiResponse<User>(
- success: true,
- message: '获取成功',
- data: user,
- );
- } else if (response.statusCode == 401) {
- // Token过期,尝试刷新
- final refreshResult = await _refreshToken();
- if (refreshResult) {
- // 刷新成功,重新获取用户信息
- return await getCurrentUser();
- } else {
- return ApiResponse<User>(
- success: false,
- message: '登录已过期,请重新登录',
- );
- }
- } else {
- return ApiResponse<User>(
- success: false,
- message: '获取用户信息失败',
- );
- }
- } catch (e) {
- return ApiResponse<User>(
- success: false,
- message: '获取失败: $e',
- );
- }
- }
-
- // 刷新Token
- Future<bool> _refreshToken() async {
- try {
- final refreshToken = _apiClient.getRefreshToken();
-
- if (refreshToken == null || refreshToken.isEmpty) {
- return false;
- }
-
- final response = await _apiClient.post(
- ApiConstants.getRefreshUrl(), // 需要添加这个常量
- {'refresh_token': refreshToken},
- withAuth: false,
- );
-
- if (response.statusCode == 200) {
- final data = json.decode(response.body);
- final newAccessToken = data['access_token'];
- final newRefreshToken = data['refresh_token'];
-
- // 保存新的tokens
- await _apiClient.saveTokens(newAccessToken, newRefreshToken);
- return true;
- }
-
- return false;
- } catch (e) {
- return false;
- }
- }
-
- // 登出
- Future<ApiResponse<bool>> logout() async {
- try {
- // 获取refresh_token
- final refreshToken = _apiClient.getRefreshToken();
-
- if (refreshToken == null || refreshToken.isEmpty) {
- // 没有refresh_token,只清除本地数据
- await _clearLocalData();
- return ApiResponse<bool>(
- success: true,
- message: '已退出登录',
- data: true,
- );
- }
-
- // 发送登出请求到服务器
- final response = await _apiClient.post(
- ApiConstants.getLogoutUrl(),
- {'refresh_token': refreshToken},
- withAuth: true, // 需要access_token认证头
- );
-
- // 无论服务器响应如何,都清除本地数据
- await _clearLocalData();
-
- if (response.statusCode == 200) {
- return ApiResponse<bool>(
- success: true,
- message: '已成功退出登录',
- data: true,
- );
- } else {
- // 服务器登出失败,但本地已清除
- return ApiResponse<bool>(
- success: true,
- message: '已退出登录(服务器通信失败)',
- data: true,
- );
- }
- } catch (e) {
- // 网络异常,仍然清除本地数据
- await _clearLocalData();
- return ApiResponse<bool>(
- success: true,
- message: '已退出登录(网络异常)',
- data: true,
- );
- }
- }
-
- // 清除本地数据
- Future<void> _clearLocalData() async {
- await _apiClient.clearTokens();
- await _prefs.remove('user_data');
- }
-
- // 检查登录状态
- Future<bool> isLoggedIn() async {
- // 检查是否有access_token
- if (!_apiClient.isLoggedIn()) {
- return false;
- }
-
- // 可以进一步验证token是否有效
- try {
- final response = await _apiClient.get(
- ApiConstants.getCurrentUserUrl(),
- withAuth: true,
- );
- return response.statusCode == 200;
- } catch (e) {
- return false;
- }
- }
- }
|