Данные аутентификации сбрасываются всякий раз, когда приложение перестраивается в Flutter

#flutter #oauth-2.0 #flutter-dependencies

#flutter #oauth-2.0 #flutter-зависимости

Вопрос:

У меня есть настройка метода аутентификации, которая расширяет ChangeNotifier для предоставления токенов входа и хранения и других сведений.

и в моем файле main.dart я вызываю мульти-провайдера, чтобы получить всех провайдеров, внутри мульти-провайдера у меня есть потребитель в качестве дочернего элемента, который решает, какую страницу вызывать по умолчанию. то есть, если auth.isAuth возвращает true, после чего будет вызван MainPage.dart или AuthScreen.dart.

Вход в систему работает нормально, и все остальное работает нормально.

Но проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я перезагружаю или перестраиваю свое приложение, данные аутентификации становятся нулевыми.

Любая помощь будет оценена. Заранее спасибо.

main.dart

 @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(
          value: Auth(),
        ),
        ChangeNotifierProvider.value(
          value: Cart(),
        ),
        ChangeNotifierProvider.value(
          value: AddressBook(Auth().token),
        ),
        ChangeNotifierProvider.value(
          value: Orders(),
        ),
      ],
      child: Consumer<Auth>(
        builder: (ctx, auth, _) => MaterialApp(
          title: 'APP NAME',
          theme: ThemeData(
              fontFamily: 'Roboto',
              primaryColor: Colors.white,
              primaryColorDark: Colors.white,
              backgroundColor: Colors.white),
          home: auth.isAuth ? MainPage() : AuthScreen(),
          routes: {
            MainPage.routeName: (ctx) => MainPage(),
            CartScreen.routeName: (ctx) => CartScreen(),
            OrderScreen.routeName: (ctx) => OrderScreen(),
            EditAddressScreen.routeName: (ctx) => EditAddressScreen(),
          }),
      ),
    );
  }
 

auth.dart

 class Auth extends ChangeNotifier {

  String _token;
  String _refresh_token;
  DateTime _expiryDate;
  int _userId;

  bool get isAuth {
    return _token != null;
  }

  String get token {
    if (_expiryDate != null amp;amp;
        _expiryDate.isAfter(DateTime.now()) amp;amp;
        _token != null) {
      return _token;
    }
    return null;
  }

  int get userId {
    return _userId;
  }

  Future<void> _authenticate(String email, String password, String urlSegment) async {
    final url = 'http://192.168.1.120:8080/oauth/token';
    Map<String, dynamic> body = {'grant_type': 'password', 'username': email, 'password': password};
    var parts = [];
    parts.add('${Uri.encodeQueryComponent("grant_type")}=${Uri.encodeQueryComponent("password")}');
    parts.add('${Uri.encodeQueryComponent("username")}=${Uri.encodeQueryComponent(email)}');
    parts.add('${Uri.encodeQueryComponent("password")}=${Uri.encodeQueryComponent(password)}');
    var formData = parts.join('amp;');
    try {
      final response = await http.post(
        url,
        body: formData,
        headers: {
          'content-type': 'application/x-www-form-urlencoded',
          'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXX',
        }
      );
      final responseData = json.decode(response.body);
      print(response.statusCode);
      if(response.statusCode != 200){
        throw HttpException(responseData['error']['error_description']);
      }else{
        _token = responseData['access_token'];
        _userId = responseData['customerId'];
        _refresh_token = responseData['refresh_token'];
        _expiryDate = DateTime.now().add(
          Duration(
            seconds: responseData['expires_in'],
          ),
        );
        notifyListeners();
      }
      if (responseData['error'] != null) {
       throw HttpException(responseData['error']['error_description']);
      }

    } catch (error) {
      throw error;
    }
  }

  Future<void> signup(String email, String password) async {
    return _authenticate(email, password, 'signUp');
  }

  Future<void> login(String email, String password) async {
    return _authenticate(email, password, 'signInWithPassword');
  }
  
}
 

Комментарии:

1. Чтобы предоставить доступ к вновь созданному объекту, используйте конструктор поставщика по умолчанию. Не используйте конструктор .value, если вы хотите создать объект, иначе у вас могут возникнуть нежелательные побочные эффекты. Использование changeNotifierprovider.value совершенно неверно.

2. можете ли вы подсказать мне, как я должен использовать всех поставщиков.

3. Удалите .value и используйте create: (_)=> вместо value и посмотрите, работает ли это

4. сделал то, что сказал, но не повезло .. все еще перенаправляет на AuthScreen.

5. я заметил, что когда я удаляю multiprovider и использую один ChangeNotifierProvider для аутентификации. он работает нормально, и mainpage.dart загружается вместо authscreen.dart

Ответ №1:

На данный момент похоже, что вы храните токены OAuth в памяти, поэтому они удаляются при каждом перезапуске, и это обеспечивает плохое удобство использования.

ХРАНИЛИЩЕ МОБИЛЬНЫХ ТОКЕНОВ

Токены OAuth можно сохранить в защищенном зашифрованном хранилище для улучшения удобства использования, возможно, используя эту библиотеку Flutter. Используемое шифрование должно быть закрытым для вашего приложения, чтобы никакое другое приложение не могло использовать токены.

СТРУКТУРИРОВАНИЕ ВАШЕГО КОДА

Мне очень нравится, как вы структурировали свой код, где остальная часть приложения просто вызывает метод getToken Auth.dart при вызове веб-API. Похоже, что ваш исходный файл Auth.dart нуждается в дополнительной работе для решения вашей проблемы.

МОЙ ПРИМЕР

Этот код написан на Swift и использует другой поток с библиотеками AppAuth. Однако общий шаблон проектирования может быть применен на любом языке, включая Flutter.