Flutter App每次登录后都会重定向到登录页面

Posted

技术标签:

【中文标题】Flutter App每次登录后都会重定向到登录页面【英文标题】:Flutter App redirecting to login page everytime after logging in 【发布时间】:2020-12-30 18:00:19 【问题描述】:

在我的 Flutter App 中,用户登录后会重定向到 LoginPage 而不是应用中的 MainPage。用户身份验证是使用 JWT 完成的。所有 API 都在一个 laravel 项目中。我已经检查了所有的 API,它们的工作方式与使用 Postman 的方式一样。提前致谢。

以下是我的 main.dart。

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:my_app/login.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: "my_app",
      debugShowCheckedModeBanner: false,
      home: MainPage(),
      theme: ThemeData(
          accentColor: Colors.white70
      ),
    );
  


class MainPage extends StatefulWidget 
  @override
  _MainPageState createState() => _MainPageState();


class _MainPageState extends State<MainPage> 

  SharedPreferences sharedPreferences;

  @override
  void initState() 
    super.initState();
    checkLoginStatus();
  

  checkLoginStatus() async 
    sharedPreferences = await SharedPreferences.getInstance();
    if(sharedPreferences.getString("token") == null) 
      Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false);
    
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Evanto App", style: TextStyle(color: Colors.white)),
        actions: <Widget>[
          FlatButton(
            onPressed: () 
              sharedPreferences.clear();
              sharedPreferences.commit();
              Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false);
            ,
            child: Text("Log Out", style: TextStyle(color: Colors.white)),
          ),
        ],
      ),
      body: Center(child: Text("Main Page")),
      drawer: Drawer(),
    );
  

登录.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:my_app/main.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LoginPage extends StatefulWidget 
  @override
  _LoginPageState createState() => _LoginPageState();


class _LoginPageState extends State<LoginPage> 

  bool _isLoading = false;

  @override
  Widget build(BuildContext context) 
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(statusBarColor: Colors.transparent));
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
              colors: [Colors.blue, Colors.teal],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter),
        ),
        child: _isLoading ? Center(child: CircularProgressIndicator()) : ListView(
          children: <Widget>[
            headerSection(),
            textSection(),
            buttonSection(),
          ],
        ),
      ),
    );
  

  signIn(String email, password) async 
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    Map data = 
      'email': email,
      'password': password
    ;
    var jsonResponse = null;
    var response = await http.post("http://my_api.com/api/auth/login", body: data);
    if(response.statusCode == 200) 
      jsonResponse = json.decode(response.body);
      if(jsonResponse != null) 
        setState(() 
          _isLoading = false;
        );
        sharedPreferences.setString("token", jsonResponse['token']);
        Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => MainPage()), (Route<dynamic> route) => false);
      
    
    else 
      setState(() 
        _isLoading = false;
      );
      print(response.body);
    
  

  Container buttonSection() 
    return Container(
      width: MediaQuery.of(context).size.width,
      height: 40.0,
      padding: EdgeInsets.symmetric(horizontal: 15.0),
      margin: EdgeInsets.only(top: 15.0),
      child: RaisedButton(
        onPressed: emailController.text == "" || passwordController.text == "" ? null : () 
          setState(() 
            _isLoading = true;
          );
          signIn(emailController.text, passwordController.text);
        ,
        elevation: 0.0,
        color: Colors.purple,
        child: Text("Sign In", style: TextStyle(color: Colors.white70)),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
      ),
    );
  

  final TextEditingController emailController = new TextEditingController();
  final TextEditingController passwordController = new TextEditingController();

  Container textSection() 
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
      child: Column(
        children: <Widget>[
          TextFormField(
            controller: emailController,
            cursorColor: Colors.white,

            style: TextStyle(color: Colors.white70),
            decoration: InputDecoration(
              icon: Icon(Icons.email, color: Colors.white70),
              hintText: "Email",
              border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
              hintStyle: TextStyle(color: Colors.white70),
            ),
          ),
          SizedBox(height: 30.0),
          TextFormField(
            controller: passwordController,
            cursorColor: Colors.white,
            obscureText: true,
            style: TextStyle(color: Colors.white70),
            decoration: InputDecoration(
              icon: Icon(Icons.lock, color: Colors.white70),
              hintText: "Password",
              border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
              hintStyle: TextStyle(color: Colors.white70),
            ),
          ),
        ],
      ),
    );
  

  Container headerSection() 
    return Container(
      margin: EdgeInsets.only(top: 50.0),
      padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 30.0),
      child: Text("Evanto App",
          style: TextStyle(
              color: Colors.white70,
              fontSize: 40.0,
              fontWeight: FontWeight.bold)),
    );
  

【问题讨论】:

【参考方案1】:

你可以试试这样的:

void main() async 
  await StorageUtil.getInstance();
  return runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: "my_app",
      home: StorageUtil.getString("token") != null ? MainPage() : LoginPage(),
      theme: ThemeData(accentColor: Colors.white70),
    );
  

要静态访问 getString,您可以创建一个实用程序类,在其中使用私有构造函数实例化您的 SharedPreferences

import 'package:shared_preferences/shared_preferences.dart';

class StorageUtil 
  static StorageUtil _storageUtil;
  static SharedPreferences _preferences;

  static Future<StorageUtil> getInstance() async 
    if (_storageUtil == null) 
      var secureStorage = StorageUtil._();
      await secureStorage._init();
      _storageUtil = secureStorage;
    
    return _storageUtil;
  

  StorageUtil._();
  Future _init() async 
    _preferences = await SharedPreferences.getInstance();
  

  // get string
  static String getString(String key, String defValue = '') 
    if (_preferences == null) return defValue;
    return _preferences.getString(key) ?? defValue;
  

【讨论】:

我得到这个:无法使用静态访问访问实例成员“getString”。 我没有发现任何错误,但这次我留下了一个白屏。

以上是关于Flutter App每次登录后都会重定向到登录页面的主要内容,如果未能解决你的问题,请参考以下文章

为啥登录后phpmyadmin会重定向到登录页面?

如何设计一个单点登录系统?

即使在登录后 Django 也会重定向到登录页面

无法在 Getx Flutter 中获取布尔值

如果尝试进入登录屏幕,Laravel 5 会重定向到主页

React 路由器会短暂显示登录屏幕,然后如果用户已登录,则会重定向到仪表板