简体   繁体   English

Flutter:如何保持用户登录和注销

[英]Flutter : How to keep user logged in and make logout

I am getting the csrf token and printing the response data in console but how to keep user logged in using the response data.I am making login using the status code ie, if status code is 200 then move to login after that I want to keep user logged in and log out only when user wants to log out我正在获取 csrf 令牌并在控制台中打印响应数据,但如何使用响应数据使用户保持登录状态。我正在使用状态代码登录,即,如果状态代码为 200,则在此之后移动到登录状态,我想保持仅当用户想注销时才登录和注销

I have seen lot of examples but none are helping in my case.我看过很多例子,但没有一个对我的情况有帮助。

In my case i am using th csrf token and unable to keep it logged in, and i have also used login form.就我而言,我使用的是 csrf 令牌并且无法保持登录状态,并且我还使用了登录表单。

LoginPage.dart登录页面.dart

import 'dart:io';

import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:jignasa/home_screen.dart';
import 'package:jignasa/logindata.dart';
import 'package:path_provider/path_provider.dart';


class LoginPage extends StatefulWidget {
  static String tag = 'login-page';
  @override
  _LoginPageState createState() => new _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  LoginRequestData _loginData = LoginRequestData();


  bool _validate = false;
  bool _obscureText = true;
  var username, password;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Container(
          color: Colors.lightGreen[500],
          child: Column(
            children: <Widget>[
              Center(
                child: Container(
                  width: MediaQuery
                      .of(context)
                      .size
                      .width,
                  height: MediaQuery
                      .of(context)
                      .size
                      .height / 2.5,
                  decoration: BoxDecoration(
                      gradient: LinearGradient(
                        // begin: Alignment.topCenter,
                        // end: Alignment.bottomCenter,
                          colors: [
                            Color(0xFFFFFFFF),
                            Color(0xFFFFFFFF),
                          ]
                      ),
                      borderRadius: BorderRadius.only(
                          bottomLeft: Radius.circular(90)
                      )
                  ),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Align(
                        alignment: Alignment.center,
                        child: Image.asset('images/ic_launcher1.png'),
                      ),
                    ],
                  ),
                ),
              ),
              Center(
                  child: SingleChildScrollView(
                    child: new Form(
                      key: _formKey,
                      autovalidate: _validate,
                      child: _getFormUI(),
                    ),
                  )
              )

            ],
          ),
        ),
      ),
    );
  }

  Widget _getFormUI() {
    return new Column(
      children: <Widget>[
        SizedBox(height: 24.0),
        Center(
          child: Text('Login',
            style: TextStyle(fontSize: 25,
                fontWeight: FontWeight.bold,
                color: Colors.white),),
        ),
        new SizedBox(height: 25.0),
        new TextFormField(
          keyboardType: TextInputType.emailAddress,
          autofocus: false,
          decoration: InputDecoration(
            hintText: 'Username',
            contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
            border:
            OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
          ),
          validator: _validateName,
          onSaved: (value) {
            _loginData.username = value;
          },
        ),
        new SizedBox(height: 8.0),
        new TextFormField(
            autofocus: false,
            obscureText: _obscureText,
            keyboardType: TextInputType.text,
            decoration: InputDecoration(
              hintText: 'Password',
              contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
              border:
              OutlineInputBorder(borderRadius: BorderRadius.circular(24.0)),
              suffixIcon: GestureDetector(
                child: Icon(
                  _obscureText ? Icons.visibility : Icons.visibility_off,
                  semanticLabel:
                  _obscureText ? 'show password' : 'hide password',
                ),
              ),
            ),
            validator: _validatePassword,
            onSaved: (String value) {
              _loginData.password = value;
            }
        ),
        new SizedBox(height: 15.0),
        new Padding(
          padding: EdgeInsets.symmetric(vertical: 16.0),
          child: RaisedButton(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(24),
            ),
            onPressed: () {
              _submit();
//              Navigator.of(context).pushReplacementNamed('/home');
            },
            padding: EdgeInsets.all(12),
            color: Colors.black54,
            child: Text('Log In', style: TextStyle(color: Colors.white)),
          ),
        ),
        new FlatButton(
          child: Text(
            'Forgot password?',
            style: TextStyle(color: Colors.black54),
          ),
          onPressed: () {},
        ),
        new FlatButton(
          onPressed: _sendToRegisterPage,
          child: Text('Not a member? Sign up now',
              style: TextStyle(color: Colors.black54)),
        ),
        Text(''),
        Text(''),
        Text(''),
      ],
    );
  }

  _sendToRegisterPage() {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => HomeScreen()),
    );
  }

  String _validateName(String value) {
    if (value.isEmpty) {
      return "Username is Required";
    } else {
      username = value.toString();
    }
  }

  String _validatePassword(String value) {
    if (value.isEmpty) {
      return "Password is Required";
    } else {
      password = value.toString();
    }
  }

  _submit() {
    if (_formKey.currentState.validate()) {
      _formKey.currentState.save();
      print("Username ${_loginData.username}");
      print("Password ${_loginData.password}");
      return SessionId();
    } else {
      setState(() {
        bool _validate = false;
      });
    }
  }


  final Dio _dio = Dio();
  PersistCookieJar persistentCookies;
  final String url = "https://www.xxxx.in/rest/user/login.json";

  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    print(directory.path);
    return directory.path;
  }

  Future<Directory> get _localCoookieDirectory async {
    final path = await _localPath;
    final Directory dir = new Directory('$path/cookies');
    await dir.create();
    print(dir);
    return dir;
  }

  Future<String> getCsrftoken() async{
    try {
      String csrfTokenValue;
      final Directory dir = await _localCoookieDirectory;
      final cookiePath = dir.path;
      persistentCookies = new PersistCookieJar(dir: '$cookiePath');
      persistentCookies.deleteAll(); //clearing any existing cookies for a fresh start
      _dio.interceptors.add(
          CookieManager(persistentCookies) //this sets up _dio to persist cookies throughout subsequent requests
      );
      _dio.options = new BaseOptions(
        baseUrl: url,
        contentType: ContentType.json,
        responseType: ResponseType.plain,
        // connectTimeout: 5000,
        // receiveTimeout: 100000,
        headers: {
          HttpHeaders.userAgentHeader: "dio",
          "Connection": "keep-alive",
        },
      ); //BaseOptions will be persisted throughout subsequent requests made with _dio
      _dio.interceptors.add(
          InterceptorsWrapper(
              onResponse:(Response response) {
                List<Cookie> cookies = persistentCookies.loadForRequest(Uri.parse(url));
                csrfTokenValue = cookies.firstWhere((c) => c.name == 'csrftoken', orElse: () => null)?.value;
                if (csrfTokenValue != null) {
                  _dio.options.headers['X-CSRF-TOKEN'] = csrfTokenValue; //setting the csrftoken from the response in the headers
                }
                print(response);
                return response;
              }
          )
      );
      await _dio.get("https://www.xxxx.in/rest/user/login.json");
      print(csrfTokenValue);
      return csrfTokenValue;
    } catch (error, stacktrace) {
      print(error);
//      print("Exception occured: $error stackTrace: $stacktrace");
      return null;
    }
  }

   SessionId() async {
     try {
       final csrf = await getCsrftoken();
       FormData formData = new FormData.from({
         "username": "${_loginData.username}",
         "password": "${_loginData.password}",
         "csrfmiddlewaretoken" : '$csrf'
       });
       Options optionData = new Options(
         contentType: ContentType.parse("application/json"),
       );
       Response response = await _dio.post("https://www.xxxx.in/rest/user/login.json", data: formData, options: optionData);
       print("StatusCode:${response.statusCode}");
      //  print(response.data);
       if (response.statusCode == 200){
         return Navigator.of(context).pushReplacement(MaterialPageRoute(
             builder: (context) => HomeScreen(),
         ));
       }
       else{
         throw Exception();
       }
     } on DioError catch(e) {
       if(e.response != null) {
         print( e.response.statusCode.toString() + " " + e.response.statusMessage);
         print(e.response.data);
         print(e.response.headers);
         print(e.response.request);
       } else{
         print(e.request);
         print(e.message);
       }
     }
     catch (error, stacktrace) {
       print("Exception occured: $error stackTrace: $stacktrace");
       return null;
     }
   }
}

You can make an entry in Shared preference after getting response code 200 from api.从 api 获取响应代码 200 后,您可以在共享首选项中进行输入。

 SharedPreferences prefs = await SharedPreferences.getInstance();
 prefs?.setBool("isLoggedIn", true);

then you can navigate user after checking status from shared preference然后您可以在从共享首选项检查状态后导航用户

Future<void> main() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  var status = prefs.getBool('isLoggedIn') ?? false;
  print(status);
  runApp(MaterialApp(home: status == true ? Login() : Home()));
}

Update :-更新 :-

Another way of doing it is you can also add your logic into splash screen and splash screen should be entry point in your app另一种方法是您还可以将您的逻辑添加到启动画面中,启动画面应该是您的应用程序的入口点

class SplashScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _SplashScreenState();
  }
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    startTimer();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
              image: AssetImage("assets/images/clinician_splash.png"),
              fit: BoxFit.cover),
        ),
      ),
    );
  }

  void startTimer() {
    Timer(Duration(seconds: 3), () {
      navigateUser(); //It will redirect  after 3 seconds
    });
  }

  void navigateUser() async{
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var status = prefs.getBool('isLoggedIn') ?? false;
    print(status);
    if (status) {
      Navigation.pushReplacement(context, "/Home");
    } else {
      Navigation.pushReplacement(context, "/Login");
    }
  }
}

For logout add below functionality in onPress event of logout button :对于注销,在注销按钮的 onPress 事件中添加以下功能:

void logoutUser(){
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs?.clear() 
 Navigator.pushAndRemoveUntil(
      context, 
      ModalRoute.withName("/SplashScreen"), 
     ModalRoute.withName("/Home")
    );
}

For security :-为了安全:-

Here in example I have used SharedPreferences which is not secure.for security you can change SharedPreferences to flutter_secure_storage.在示例中,我使用了不安全的 SharedPreferences。为了安全起见,您可以将 SharedPreferences 更改为 flutter_secure_storage。

https://pub.dev/packages/flutter_secure_storage#-readme-tab-https://pub.dev/packages/flutter_secure_storage#-readme-tab-

I am getting the csrf token and printing the response data in console but how to keep user logged in using the response data.I am making login using the status code ie, if status code is 200 then move to login after that I want to keep user logged in and log out only when user wants to log out我正在获取csrf令牌并在控制台中打印响应数据,但是如何使用响应数据保持用户登录。我正在使用状态码进行登录,即如果状态码为200,则在此之后继续登录用户登录并仅在用户要注销时才注销

I have seen lot of examples but none are helping in my case.我已经看到了很多示例,但对我而言没有任何帮助。

In my case i am using th csrf token and unable to keep it logged in, and i have also used login form.就我而言,我正在使用csrf令牌,并且无法保持其登录状态,并且我还使用了登录表单。

LoginPage.dart LoginPage.dart

import 'dart:io';

import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:jignasa/home_screen.dart';
import 'package:jignasa/logindata.dart';
import 'package:path_provider/path_provider.dart';


class LoginPage extends StatefulWidget {
  static String tag = 'login-page';
  @override
  _LoginPageState createState() => new _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  LoginRequestData _loginData = LoginRequestData();


  bool _validate = false;
  bool _obscureText = true;
  var username, password;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Container(
          color: Colors.lightGreen[500],
          child: Column(
            children: <Widget>[
              Center(
                child: Container(
                  width: MediaQuery
                      .of(context)
                      .size
                      .width,
                  height: MediaQuery
                      .of(context)
                      .size
                      .height / 2.5,
                  decoration: BoxDecoration(
                      gradient: LinearGradient(
                        // begin: Alignment.topCenter,
                        // end: Alignment.bottomCenter,
                          colors: [
                            Color(0xFFFFFFFF),
                            Color(0xFFFFFFFF),
                          ]
                      ),
                      borderRadius: BorderRadius.only(
                          bottomLeft: Radius.circular(90)
                      )
                  ),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Align(
                        alignment: Alignment.center,
                        child: Image.asset('images/ic_launcher1.png'),
                      ),
                    ],
                  ),
                ),
              ),
              Center(
                  child: SingleChildScrollView(
                    child: new Form(
                      key: _formKey,
                      autovalidate: _validate,
                      child: _getFormUI(),
                    ),
                  )
              )

            ],
          ),
        ),
      ),
    );
  }

  Widget _getFormUI() {
    return new Column(
      children: <Widget>[
        SizedBox(height: 24.0),
        Center(
          child: Text('Login',
            style: TextStyle(fontSize: 25,
                fontWeight: FontWeight.bold,
                color: Colors.white),),
        ),
        new SizedBox(height: 25.0),
        new TextFormField(
          keyboardType: TextInputType.emailAddress,
          autofocus: false,
          decoration: InputDecoration(
            hintText: 'Username',
            contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
            border:
            OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
          ),
          validator: _validateName,
          onSaved: (value) {
            _loginData.username = value;
          },
        ),
        new SizedBox(height: 8.0),
        new TextFormField(
            autofocus: false,
            obscureText: _obscureText,
            keyboardType: TextInputType.text,
            decoration: InputDecoration(
              hintText: 'Password',
              contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
              border:
              OutlineInputBorder(borderRadius: BorderRadius.circular(24.0)),
              suffixIcon: GestureDetector(
                child: Icon(
                  _obscureText ? Icons.visibility : Icons.visibility_off,
                  semanticLabel:
                  _obscureText ? 'show password' : 'hide password',
                ),
              ),
            ),
            validator: _validatePassword,
            onSaved: (String value) {
              _loginData.password = value;
            }
        ),
        new SizedBox(height: 15.0),
        new Padding(
          padding: EdgeInsets.symmetric(vertical: 16.0),
          child: RaisedButton(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(24),
            ),
            onPressed: () {
              _submit();
//              Navigator.of(context).pushReplacementNamed('/home');
            },
            padding: EdgeInsets.all(12),
            color: Colors.black54,
            child: Text('Log In', style: TextStyle(color: Colors.white)),
          ),
        ),
        new FlatButton(
          child: Text(
            'Forgot password?',
            style: TextStyle(color: Colors.black54),
          ),
          onPressed: () {},
        ),
        new FlatButton(
          onPressed: _sendToRegisterPage,
          child: Text('Not a member? Sign up now',
              style: TextStyle(color: Colors.black54)),
        ),
        Text(''),
        Text(''),
        Text(''),
      ],
    );
  }

  _sendToRegisterPage() {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => HomeScreen()),
    );
  }

  String _validateName(String value) {
    if (value.isEmpty) {
      return "Username is Required";
    } else {
      username = value.toString();
    }
  }

  String _validatePassword(String value) {
    if (value.isEmpty) {
      return "Password is Required";
    } else {
      password = value.toString();
    }
  }

  _submit() {
    if (_formKey.currentState.validate()) {
      _formKey.currentState.save();
      print("Username ${_loginData.username}");
      print("Password ${_loginData.password}");
      return SessionId();
    } else {
      setState(() {
        bool _validate = false;
      });
    }
  }


  final Dio _dio = Dio();
  PersistCookieJar persistentCookies;
  final String url = "https://www.xxxx.in/rest/user/login.json";

  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    print(directory.path);
    return directory.path;
  }

  Future<Directory> get _localCoookieDirectory async {
    final path = await _localPath;
    final Directory dir = new Directory('$path/cookies');
    await dir.create();
    print(dir);
    return dir;
  }

  Future<String> getCsrftoken() async{
    try {
      String csrfTokenValue;
      final Directory dir = await _localCoookieDirectory;
      final cookiePath = dir.path;
      persistentCookies = new PersistCookieJar(dir: '$cookiePath');
      persistentCookies.deleteAll(); //clearing any existing cookies for a fresh start
      _dio.interceptors.add(
          CookieManager(persistentCookies) //this sets up _dio to persist cookies throughout subsequent requests
      );
      _dio.options = new BaseOptions(
        baseUrl: url,
        contentType: ContentType.json,
        responseType: ResponseType.plain,
        // connectTimeout: 5000,
        // receiveTimeout: 100000,
        headers: {
          HttpHeaders.userAgentHeader: "dio",
          "Connection": "keep-alive",
        },
      ); //BaseOptions will be persisted throughout subsequent requests made with _dio
      _dio.interceptors.add(
          InterceptorsWrapper(
              onResponse:(Response response) {
                List<Cookie> cookies = persistentCookies.loadForRequest(Uri.parse(url));
                csrfTokenValue = cookies.firstWhere((c) => c.name == 'csrftoken', orElse: () => null)?.value;
                if (csrfTokenValue != null) {
                  _dio.options.headers['X-CSRF-TOKEN'] = csrfTokenValue; //setting the csrftoken from the response in the headers
                }
                print(response);
                return response;
              }
          )
      );
      await _dio.get("https://www.xxxx.in/rest/user/login.json");
      print(csrfTokenValue);
      return csrfTokenValue;
    } catch (error, stacktrace) {
      print(error);
//      print("Exception occured: $error stackTrace: $stacktrace");
      return null;
    }
  }

   SessionId() async {
     try {
       final csrf = await getCsrftoken();
       FormData formData = new FormData.from({
         "username": "${_loginData.username}",
         "password": "${_loginData.password}",
         "csrfmiddlewaretoken" : '$csrf'
       });
       Options optionData = new Options(
         contentType: ContentType.parse("application/json"),
       );
       Response response = await _dio.post("https://www.xxxx.in/rest/user/login.json", data: formData, options: optionData);
       print("StatusCode:${response.statusCode}");
      //  print(response.data);
       if (response.statusCode == 200){
         return Navigator.of(context).pushReplacement(MaterialPageRoute(
             builder: (context) => HomeScreen(),
         ));
       }
       else{
         throw Exception();
       }
     } on DioError catch(e) {
       if(e.response != null) {
         print( e.response.statusCode.toString() + " " + e.response.statusMessage);
         print(e.response.data);
         print(e.response.headers);
         print(e.response.request);
       } else{
         print(e.request);
         print(e.message);
       }
     }
     catch (error, stacktrace) {
       print("Exception occured: $error stackTrace: $stacktrace");
       return null;
     }
   }
}
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences preferences = await SharedPreferences.getInstance();
var email = preferences.getString("emailText");

runApp(
  MaterialApp(
    home: email == null ? LoginPage() : Dashboard(),
  )
);

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM