flutter - 如何使用Flutter使用BloC访问登录时获得的身份验证 token

标签 flutter web dart mobile bloc

我已经完成了下面的https://dev.to/amartyadev/flutter-app-authentication-with-django-backend-1-21cp教程,该教程虽然很有用,但对如何继续前进仍然一无所知。我能够登录,并且用户详细信息通过UserRepository类(包括身份验证 token )通过UserRepository类保存到本地的sqlite数据库中,但是当尝试向服务器重复请求数据时,我不知道如何访问它。现有代码没有任何问题,但是我将展示几页,这样您就可以看到我已经做过并且正在尝试实现以及如何将它们组合在一起。
main.dart:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import './repository/user_repository.dart';

import './bloc/authentication/authentication_bloc.dart';
import './screens/splash_screen.dart';
import './screens/login/login_screen.dart';
import './screens/home_screen.dart';
import './widgets/loading_indicator.dart';
import './widgets/video_widget.dart';
import './screens/home_screen.dart';

const welcomeUrl = 'https://soundjudgement.github.io/static-sf/tour.mp4';
class SimpleBlocDelegate extends BlocDelegate {
  @override
  void onEvent(Bloc bloc, Object event) {
    super.onEvent(bloc, event);
    print(event);
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    print(transition);
  }

  @override
  void onError(Bloc bloc, Object error, StackTrace stacktrace) {
    super.onError(bloc, error, stacktrace);
  }
}

void main() {
  BlocSupervisor.delegate = SimpleBlocDelegate();
  final userRepository = UserRepository();

  runApp(BlocProvider<AuthenticationBloc>(
    create: (context) {
      return AuthenticationBloc(userRepository: userRepository)
        ..add(AppStarted());
    },
    child: SundayFundayApp(userRepository: userRepository),
  ));
}

class SundayFundayApp extends StatelessWidget {
  // This widget is the root of your application.

  final UserRepository userRepository;

  SundayFundayApp({Key key, @required this.userRepository}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'The Yard Mobile App',
      theme: ThemeData(
        primarySwatch: Colors.yellow,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (context, state) {
          if (state is AuthenticationUnintialized) {
            return SplashPage();
          }
          if (state is AuthenticationAuthenticated) {
            return HomeScreen();
          }
          if (state is AuthenticationUnauthenticated) {
            return LogInScreen(
              userRepository: userRepository,
            );
          }
          if (state is AuthenticationLoading) {
            return LoadingIndicator();
          }
        },
      ),
    );
  }
}
user_repository.dart
import 'dart:async';
import '../models/user_model.dart';
import 'package:meta/meta.dart';
import '../models/api_model.dart';
import '../api_connection/api_connection.dart';
import '../dba/user_dba.dart';

class UserRepository {
  final userDao = UserDba();

  Future<User> authenticate({
    @required String username,
    @required String password,
  }) async {
    UserLogin userLogin = UserLogin(username: username, password: password);
    Token token = await getToken(userLogin);
    User user = User(
      id: 0,
      username: username,
      token: token.token,
    );
    return user;
  }

  Future<void> persistToken({@required User user}) async {
    // write token with the user to the database
    await userDao.createUser(user);
  }

  Future<void> deleteToken({@required int id}) async {
    await userDao.deleteUser(id);
  }

  Future<bool> hasToken() async {
    bool result = await userDao.checkUser(0);
    return result;
  }
}
user_dao.dart:
import '../database/user_database.dart';
import '../models/user_model.dart';

class UserDao {
  final dbProvider = DatabaseProvider.dbProvider;

  Future<int> createUser(User user) async {
    final db = await dbProvider.database;

    var result = db.insert(userTable, user.toDatabaseJson());
    return result;
  }

  Future<int> deleteUser(int id) async {
    final db = await dbProvider.database;
    var result = await db
        .delete(userTable, where: "id = ?", whereArgs: [id]);
    return result;
  }

  Future<bool> checkUser(int id) async {
    final db = await dbProvider.database;
    try {
      List<Map> users = await db
          .query(userTable, where: 'id = ?', whereArgs: [id]);
      if (users.length > 0) {
        return true;
      } else {
        return false;
      }
    } catch (error) {
      return false;
    }
  }
}
login_screen.dart:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../repository/user_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../bloc/authentication/authentication_bloc.dart';
import './bloc/login_bloc.dart';
import 'login_form.dart';

class LogInScreen extends StatelessWidget {

  final UserRepository userRepository;

  LogInScreen({Key key, @required this.userRepository})
      : assert(userRepository != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text('The Yard App'),
      ),
      body:  Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage('assets/images/theyardbook.png'),
              fit: BoxFit.cover,
          )
        ),
      child: BlocProvider(
          create: (context) {
            return LoginBloc(
              authenticationBloc: BlocProvider.of<AuthenticationBloc>(context),
              userRepository: userRepository,
            );
          },
        child: Container(
           child: Scaffold(
            backgroundColor: Colors.transparent,
            body: Container(
              width: MediaQuery.of(context).size.width,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(20),
                color: Colors.transparent,
              ),
              child: Padding(
                padding: EdgeInsets.all(23),
                child:     LoginForm(),

                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
用户登录后,该应用会将您带到主屏幕,在这个屏幕上,我放置了一个按钮,将我带到另一个屏幕,该屏幕将从服务器获取数据以进行显示。现在唯一可用的数据是一个注册用户,这很好,我只需要查看它的工作原理,因为我完全被卡住了,已经呆了3天了。我需要知道的是如何访问身份验证 token ?我假设(希望)访问保存到本地数据库的任何数据的过程都是相同的。
TIA
我可以复制和粘贴更多代码,但是我觉得这里有很多东西,而且教程很清楚,它可以帮助我完成最后的工作。

最佳答案

所以这是user-dao中的代码,我只需要将其导入需要访问服务器的任何小部件/类中即可。似乎很明显,而且很简单,但是在我不熟悉的所有Dart代码以及bloc模式中使用的许多文件中,我认为我的头脑变得困惑了。

  Future<String> getUserToken(int id) async {
    final db = await dbProvider.database;
    try {
      var res = await db.rawQuery("SELECT token FROM userTable WHERE id=0");
      return res.isNotEmpty ? (User.fromDatabaseJson(res.first)).token : null;
    } catch (err) {
      return null;
    }
  }

这是使用FutureBuilder的新users_screen代码
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../widgets/logout_button.dart';
import '../repository/user_repository.dart';
import 'package:http/http.dart' as http;
import '../dao/user_dao.dart';
import '../api_connection/api_connection.dart';
import '../models/user_model.dart';

class UserScreen extends StatefulWidget {

  @override
  _UserScreenState createState() => _UserScreenState();
}

class _UserScreenState extends State<UserScreen> {

  Future<User> futureUser;

  @override
  void initState() {
    super.initState();
    futureUser = getUser();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('The Yard Users'),
      ),
      body: Container(
        child: FutureBuilder( // use a future builder widget
          future: futureUser, // assign the future
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Column(
                // show your layout if future is done
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.only(left: 30.0),
                    child: Text(
                      'Username: ${snapshot.data.username}', // get the username from the snapshot
                      style: TextStyle(
                        fontSize: 24.0,
                      ),
                    ),
                  ),
                  // Logout button
                  Padding(
                    padding: EdgeInsets.fromLTRB(34.0, 20.0, 0.0, 0.0),
                    child: Container(
                        width: MediaQuery.of(context).size.width * 0.85,
                        height: MediaQuery.of(context).size.width * 0.16,
                        child: LogoutButton()
                    ),
                  ),
                ],
              );
            } else {
              return CircularProgressIndicator(); // show a progress indicator while future is executing
            }
          },
        ),
      ),
    );
  }
}

关于flutter - 如何使用Flutter使用BloC访问登录时获得的身份验证 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63605837/

相关文章:

dart - 如何使用 Flutter 实现 UserAccountsDrawerHeader 小部件的 AccountDetail 以与 Gmail 应用程序一样显示?

android - flutter :打开Facebook Messenger时出现ERR_UNKOWN_URL_SCHEME

android - 应用级别的gradle文件中flutterversionNameflutterVersionCode的flutter问题

flutter - 如何在Flutter中使用SQFLite创建多个表?

http - Golang 创建动态函数(在运行时)

html - 编辑 "alt"文本

firebase - 为什么文档不存在。但始终 !snapshot.hasData 都是 false

python - 需要在 Flask 中编写 View 函数的代码方面的帮助 - Python Web 框架

dart - 如何使用 dart-protobuf

dart - Dart 中的 net::ERR_UNSAFE_PORT