1.Firebase 身份驗證
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
Stream<User?> get authStateChanges => _auth.authStateChanges();
// Email/Password
Future<UserCredential> register(String email, String password) async {
return _auth.createUserWithEmailAndPassword(email: email, password: password);
}
Future<UserCredential> login(String email, String password) async {
return _auth.signInWithEmailAndPassword(email: email, password: password);
}
// Google Sign-In
Future<UserCredential> signInWithGoogle() async {
final googleUser = await GoogleSignIn().signIn();
final googleAuth = await googleUser!.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
return _auth.signInWithCredential(credential);
}
Future<void> signOut() async {
await GoogleSignIn().signOut();
await _auth.signOut();
}
}
2. 使用 Riverpod 驗證狀態
final authServiceProvider = Provider<AuthService>((ref) => AuthService());
final authStateProvider = StreamProvider<User?>((ref) {
return ref.watch(authServiceProvider).authStateChanges;
});
// Router guard
final routerProvider = Provider<GoRouter>((ref) {
final authState = ref.watch(authStateProvider);
return GoRouter(
redirect: (context, state) {
final isLoggedIn = authState.valueOrNull != null;
final isLoginRoute = state.matchedLocation == '/login';
if (!isLoggedIn && !isLoginRoute) return '/login';
if (isLoggedIn && isLoginRoute) return '/home';
return null;
},
routes: [/* ... */],
);
});
3. JWT 代幣管理
class TokenManager {
static const _storage = FlutterSecureStorage();
Future<void> saveTokens({required String access, required String refresh}) async {
await _storage.write(key: 'access_token', value: access);
await _storage.write(key: 'refresh_token', value: refresh);
}
Future<String?> get accessToken => _storage.read(key: 'access_token');
Future<String?> get refreshToken => _storage.read(key: 'refresh_token');
Future<void> clear() => _storage.deleteAll();
}
// Dio interceptor — auto-refresh token
class AuthInterceptor extends Interceptor {
final TokenManager _tokenManager;
final Dio _dio;
AuthInterceptor(this._tokenManager, this._dio);
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
final token = await _tokenManager.accessToken;
if (token != null) options.headers['Authorization'] = 'Bearer $token';
handler.next(options);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401) {
final refresh = await _tokenManager.refreshToken;
if (refresh != null) {
try {
final response = await _dio.post('/auth/refresh', data: {'refresh_token': refresh});
await _tokenManager.saveTokens(
access: response.data['access_token'],
refresh: response.data['refresh_token'],
);
// Retry request
final retryResponse = await _dio.fetch(err.requestOptions);
handler.resolve(retryResponse);
return;
} catch (_) {
await _tokenManager.clear();
}
}
}
handler.next(err);
}
}
4. 生物辨識認證
class BiometricService {
final _auth = LocalAuthentication();
Future<bool> get isAvailable async {
final canCheck = await _auth.canCheckBiometrics;
final isSupported = await _auth.isDeviceSupported();
return canCheck && isSupported;
}
Future<bool> authenticate() async {
return _auth.authenticate(
localizedReason: 'Xác thực để truy cập ứng dụng',
options: const AuthenticationOptions(biometricOnly: true),
);
}
}
下一篇: 動畫和動作。