#flutter #dart
#флаттер #dart
Вопрос:
Хорошо, добрый день всем, здесь возникает вопрос:
Я начал использовать flutter для мобильного интерфейса, это довольно приятно. Но я не могу понять идею обработки токена jwt и перенаправления, если он существует.
Рассмотрим небольшое приложение, позвольте мне упростить:
final storage = FlutterSecureStorage(); # init storage here?
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: LoginPage(), # want home page actually, smth like if storage is empty, then call loginpage, if storage is not empty - try to make http request, if request is okay and data received - show homepage, if request is rejected - login to obtain new jwt
);
}
}
http-запрос:
Future<User> userLogin(String login, String password) async {
Response response = await post('$_apiUrl' '/' '$_loginUrl',
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'login': login,
'password': password,
}));
if (response.statusCode == 200) {
return User.fromJson(json.decode(response.body));
} else {
throw HttpException(
'Error making login request. Status code: ${response.statusCode}');
}
}
Пользовательский класс:
class User {
final String token;
final String uuid;
final String login;
final String email;
final String firstName;
final String lastName;
User({this.token, this.uuid, this.login, this.email, this.firstName, this.lastName});
factory User.fromJson(Map<String, dynamic> json) {
return User(
token: json['token'],
uuid: json['user']['uuid'],
login: json['user']['login'],
email: json['user']['email'],
firstName: json['user']['firstName'],
lastName: json['user']['lastName'],
);
}
}
Итак, как это работает сейчас:
В основном файле на данный момент я вызываю страницу входа с кнопкой:
FlatButton(
child: Text(
'Sign in',
style: TextStyle(
color: Colors.black,
),
),
color: Colors.white,
onPressed: () {
Future<User> user = ApiRequestController().userLogin('alex', 'alex123');
Navigator.push(context, MaterialPageRoute(builder: (context) {
return UserProfile(userData: user,);
}));
},
),
Затем я перенаправляюсь на профиль пользователя, ничего интересного:
class UserProfile extends StatefulWidget {
UserProfile({this.userData});
final userData;
@override
_UserProfileState createState() => _UserProfileState();
}
class _UserProfileState extends State<UserProfile> {
@override
void initState() {
// TODO: implement initState
super.initState();
futureUser = widget.userData;
print(futureUser);
}
Future<User> futureUser;
@override
Widget build(BuildContext context) {
common stuff like scaffold etc
And then I build a profile:
FutureBuilder<User>(
future: futureUser,
builder: (context, snapshot) {
if (snapshot.hasData) {
dynamic userProfile = snapshot.data;
return Column(
children: [
Container(
child: ListTile(
title: Text(
'login: ' '${userProfile.login}',
style: TextStyle(
color: Colors.black,
),
),
),
),
Container(
child: ListTile(
title: Text(
'uuid: ' '${userProfile.uuid}',
style: TextStyle(
color: Colors.black,
),
),
),
),
Container(
child: ListTile(
title: Text(
'First name: ' '${userProfile.firstName}',
style: TextStyle(
color: Colors.black,
),
),
),
),
Container(
child: ListTile(
title: Text(
'Last name: ' '${userProfile.lastName}',
style: TextStyle(
color: Colors.black,
),
),
),
),
Container(
child: ListTile(
title: Text(
'Auth token: ' '${userProfile.token}',
style: TextStyle(
color: Colors.black,
),
),
),
),
],
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return CircularProgressIndicator();
},
),
Интерфейс упрощен для облегчения понимания.
Итак, что у меня есть сейчас, у меня есть основной файл dart, где я вызываю экран входа в систему (не домашний экран, потому что я не могу понять, как использовать токен), где я вызываю асинхронный http-запрос к api, затем я перенаправляюсь в профиль пользователя.
Идея очень проста:
- Приложение открыто -> отправить http-запрос с существующим заголовком аутентификации, если ответ равен 200, затем показать домашнюю страницу
- Если ответ не был равен 200 (токен истек / поврежден / не существует, проверено на стороне сервера), затем перейдите к экрану входа в систему, чтобы получить новый токен аутентификации
- Как правильно хранить проклятый токен jwt -_-? Я несколько раз пробовал использовать фьючерсы, простые запросы, я не могу понять, как анализировать токен между несколькими экранами.
Что мне делать? Где инициализировать токен? Где его хранить? Как я могу вызвать его из другого виджета? Я читал о InheritedWidget, хорошо. Но, т.Е., Моя домашняя страница уже расширяет StatefulWidget, и множественного наследования нет. Расширить его до пользовательского класса или что?
Итак, я застрял с этой простой целью и не могу двигаться дальше. Просто нужно проверить, существует ли токен -> показать home, если нет — показать login. После того, как мы получим правильный токен, мы можем использовать все приложение целиком, выполняя каждый запрос с использованием токена аутентификации, полученного на первом экране входа в систему.
Где инициализировать токен? Где я должен наследовать InheritedWidget? Модель? Страница просмотра? Где? Сбой архитектуры: (
Помощь очень ценится! Заранее спасибо
Комментарии:
1. Существует пакет flutter, который называется
flutter_secure_storage
you, вы можете использовать его для сохранения токена2. В вашем случае я бы использовал
flutter_secure_storage
andprovider
, поэтому загружает токен из локального хранилища только один раз, и каждый раз, когда он вам нужен, вы можете получить его в любом виджете, используя provider. вы также можете хранить информацию о пользователе, используя того же поставщика.3. Ребята, в первом блоке кода есть защищенное хранилище flutter.
4. Вопрос в том, где его использовать? Основной файл? Специальный класс для наследования? Где?