web-dev-qa-db-fra.com

Gérer les détails des utilisateurs sociaux dans l'application Google Flutter

Je suis un débutant dans le développement d'applications Flutter et j'essaie de créer un exemple d'application à des fins éducatives. Ces dernières semaines, j'ai décidé de faire un exemple d'application dans flutter qui n'a pas de section de connexion ou d'inscription intégrée, car il a des options de connexion sociale comme Facebook et Google. J'ai cherché sur le Web et obtenu de nombreux exemples de code pour savoir comment implémenter l'authentification Facebook et Google dans l'application Flutter.

J'ai un doute sur cette implémentation de connexion sociale, peut-être que cela se produit en raison du manque d'expérience de travail au niveau de l'architecture des applications mobiles. À ce stade, je me pose une question "Comment gérer les utilisateurs de connexion sociale dans les applications"

J'ai une solution comme si l'utilisateur peut se connecter avec succès, stocker les détails de l'utilisateur dans notre base de données (Firebase) vérifier que l'e-mail de l'utilisateur existe dans la base de données s'il n'y a pas d'entrées correspondantes dans la base de données, il créera un nouvel utilisateur dans la base de données ou s'il existe une mise à jour la dernière heure de la date de connexion de cet utilisateur particulier. Étant donné que cette application affiche des données liées à l'utilisateur sous d'autres formes, elle fonctionne sur la base de l'ID utilisateur connecté, j'ai donc besoin de stocker les détails de l'utilisateur connecté dans la base de données.

6
Ragesh S

En utilisant la connexion intégrée à l'aide du SDK d'authentification Firebase ( Guide officiel ), vous pourrez obtenir des informations de connexion pour différentes plateformes comme Google, Twitter, Facebook et même Github.

Vous n'avez pas besoin de coder votre propre connexion/inscription, tout est sans tracas en utilisant la bonne fonction de Firebase.

Après cela, vous aurez les informations de connexion comme ça (cela vient de la connexion par e-mail mais Facebook, Google, Twitter et Github sont disponibles):

enter image description here

Vous pouvez ensuite lier l'identifiant ou l'UID utilisateur aux informations de votre base de données.

enter image description here

Oh et enfin, n'oubliez pas de définir le paramètre de persistance pour que le fournisseur de connexion conserve la connexion de l'utilisateur après avoir fermé ses applications.

2
CheunYee

Vous devez diviser l'application Flutter en 2 parties:

  1. La partie "principale" de l'application. Il affiche les données liées à l'utilisateur.
  2. Se connecter/s'inscrire.

La logique est assez simple. Au démarrage de l'application, vous vérifiez si l'utilisateur est authentifié. Si oui, dirigez-le vers l'écran principal. Sinon, présentez-lui un écran d'inscription. Voici comment cela peut être réalisé en utilisant Firebase comme backend:

final currentUser = await FirebaseAuth.instance.currentUser();
if (currentUser != null){
  // We're good: the user is authenticated.
  // Show him the main screen.
  Navigator.of(context).pushReplacement(MaterialPageRoute(
    builder: (context) => HomeScreen()
  ));
} else {
  // The user is not logged in.
  // Show him the sign in/sign up screen.
  Navigator.of(context).pushReplacement(MaterialPageRoute(
    builder: (context) => SignInScreen()
  ));
}
2
Andrey Gordeev

vous devez utiliser la logique de jeton (utilisée par Google et Facebook).

vous devez générer un jeton pour chaque utilisateur et le stocker dans votre base de données. grâce à ce jeton, vous pouvez tout gérer sur l'utilisateur. lorsque vous appelez Facebook pour authentifier, il vous rendra un jeton pour un utilisateur spécifique. ce jeton lorsque vous l'envoyez à nouveau sur facebook ou google, ils vous répondront avec les détails de l'utilisateur. afin que vous puissiez travailler comme eux .. créer un jeton pour l'utilisateur et le rappeler pour les informations de votre base de données .. et vous pouvez stocker le jeton répondu de facebook et le faire correspondre à l'avenir .. le but de ma réponse d'aller et recherchez le concept de jeton car cela vous apportera de nombreux avantages.

2
alhussien aldali

Peut-être que cet exemple répond à vos besoins:

https://github.com/instaflutter/flutter-login-screen-firebase-auth-facebook-login

Si vous avez besoin d'aide pour comprendre, je peux vous aider!

2

L'idée est simple. Les utilisateurs se connectent avec facebook/google/instagram et obtiennent un accessToken des services mentionnés ci-dessus. Ce jeton doit être envoyé avec chaque demande nécessitant une authentification.

Utilisez le stockage Flutter pour enregistrer la persistance du jeton: https://pub.dev/packages/flutter_secure_storage

Je vais vous poster un exemple d'une de mes applis Flutter où j'ai implémenté la connexion avec instagram.

Reprise du code ci-dessous:

  • loginService.Dart est responsable des appels de connexion à l'API et de l'enregistrement du jeton dans le stockage
  • main.Dart est la première vue de l'application. Ici, si l'utilisateur n'est pas connecté, le widget de connexion s'affiche (le LoginWidget est dans login.Dart).
  • login.Dart est la vue de la page de connexion. Il y a un bouton qui appelle les fonctions de la classe LoginService

Voici le code:

~/lib/service/loginService.Dart

import 'Dart:async';
import 'Dart:convert' as JSON;
import 'package:http/http.Dart' as http;
import 'package:flutter_webview_plugin/flutter_webview_plugin.Dart';
import 'package:choose/model/User.Dart';
import 'package:flutter_secure_storage/flutter_secure_storage.Dart';
import 'package:choose/config.Dart' as config;

String apiBaseUrl = config.apiBase;
String apiPort = config.port;

class LoginService {

  String clientID;
  String secretID;
  String redirectURI;
  final FlutterSecureStorage storage = new FlutterSecureStorage();
  final String authKey = "token";

  LoginService(this.clientID, this.secretID, this.redirectURI);

  String get authenticationURI {
    return "https://api.instagram.com/oauth/authorize/?client_id=$clientID&redirect_uri=$redirectURI&response_type=code";
  }

  String get authorizationURI {
    return "https://api.instagram.com/oauth/access_token";
  }

  Future<User> authenticate() async {
    clean();
    FlutterWebviewPlugin _flutterWebviewPlugin = FlutterWebviewPlugin();

    // Stream<String> onCode = await _openServer();
    _flutterWebviewPlugin.launch(
        authenticationURI
    );

    Completer<User> loginCompleter = Completer();

    _flutterWebviewPlugin.onStateChanged.listen((viewState) async {
      String url = viewState.url;
      int indexOfCode = url.lastIndexOf("?code=");

      if(url != null && indexOfCode >= 0 && viewState.type == WebViewState.finishLoad) {
        String code = url.substring(url.indexOf('?code=') + 6, url.length);

        http.Response userResponse = await http.get(
          "${config.endpoints['getUserByCode']}?code=$code",
        );
        if(userResponse.statusCode == 200) {
          User user = User.fromMap(JSON.jsonDecode(userResponse.body));
          saveToken(user.token);
          loginCompleter.complete(user);
        } else {
          loginCompleter.completeError("User not found");
        }
        _flutterWebviewPlugin.close();
      }
    });



    return loginCompleter.future;
  }

  void saveToken(token) async {
    storage.write(key: authKey, value: token);
  }

  void clean() async {
    storage.delete(key: authKey);
  }

  Future<String> getToken() async {
    return storage.read(key: authKey);
  }

  static Future<String> getStaticToken() async {
    FlutterSecureStorage storage = FlutterSecureStorage();
    return storage.read(key: "token");
  }

}

~ lib/main.Dart

import 'package:choose/friends.Dart';
import 'package:choose/model/User.Dart';
import 'package:flutter/material.Dart';
import 'package:choose/login.Dart';
import 'package:choose/service/loginService.Dart';
import 'package:web_socket_channel/io.Dart';

import 'feed.Dart';
import 'notification.Dart';
import 'newPost.Dart';
import 'config.Dart' as config;

void main() => runApp(MyApp());

LoginService loginService = new LoginService(
  "71b818abd18043fb8b7c1833912b62ae",
  "3d9d6f87d2354085a74534c13bdda51f",
  config.endpoints['authorize'],
);



class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
      routes: {
        '/feed': (context) => DefaultTabController(
          length: 2,
          child: FeedWidget()
        ),
        '/newpost': (context) => NewPost(),
        '/notifications': (context) => NotificationWidget(
          channel: IOWebSocketChannel.connect(config.websocketURI)
        ),
        '/friends': (context) => FriendsWidget(),
      }

    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  User user;
  String label = 'Continue with Instagram';

  void openLoginPage() async {

    try {
      User _user = await loginService.authenticate();
      this.openPostPage();
    } catch(e) {
      this.setState(() {
        label = 'Try Again';
      });
    }

  }

  void openPostPage() async {
    print(await loginService.getToken());
    print("token");

    Navigator.pushReplacementNamed(context, '/feed');
  }

  void actionDelegator() {
    if(user != null) {
      return openPostPage();
    } else {
      return openLoginPage();
    }
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Login(loginAction: actionDelegator, user: user, label: label);
  }
}

~/lib/service/login.Dart

import 'package:flutter/material.Dart';
import 'package:font_awesome_flutter/font_awesome_flutter.Dart';
import 'package:choose/model/User.Dart';

class Login extends StatefulWidget {

  Login({this.loginAction, this.user, this.label});

  final loginAction;
  final User user;
  final String label;

  _Login createState() => _Login();

}

class _Login extends State<Login> {

  String imageURI = "https://www.travelcontinuously.com/wp-content/uploads/2018/04/empty-avatar.png";

  @override
  Widget build(BuildContext context) {

    if(widget.user != null && widget.user.profilePicture != '' ) {
      imageURI = widget.user.profilePicture;
    }

    return Container (
      color: Colors.green,
      child: Column (
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          CircleAvatar (
            backgroundColor: Colors.transparent,
            radius: 50.0,
            backgroundImage: NetworkImage(imageURI, scale: 2.0),
          ),

          Container(
            padding: EdgeInsets.all(0.0),
            margin: EdgeInsets.all(20.0),
            color: Colors.transparent,
            child: MaterialButton(
              elevation: 5.0,
              color: Color.fromRGBO(193, 53, 132, 1.0),
              child: FlatButton.icon(
                label: Text(widget.label, style: TextStyle(color: Color.fromRGBO(255,220,128, 1.0), fontWeight: FontWeight.w900, fontSize: 16.0)),
                icon: Icon(FontAwesomeIcons.instagram, color: Color.fromRGBO(255,220,128, 1.0)),
              ),
              onPressed: () async {
                widget.loginAction();
              },
            )
          )
        ],
      ),
    );
  }

}
1
Andrei Todorut