当我在标签之间导航时自动注销问题(Firebase Auth rest API)

Posted

技术标签:

【中文标题】当我在标签之间导航时自动注销问题(Firebase Auth rest API)【英文标题】:problem automatic log off when I navigate between tabs (Firebase Auth rest API) 【发布时间】:2021-11-13 15:26:02 【问题描述】:

您好,我正在构建一个应用程序,我正在使用 Firebase Auth rest API 进行身份验证,但问题是当我在标签之间导航时,我的应用程序会自动注销,我不知道是令牌过期问题还是其他问题那么有人可以帮忙吗?

这是我的身份验证部分,它在我的提供程序包中

class Auth with ChangeNotifier 
   String _token;
   String _userId; 
   bool get isAuth 
      return token != null;
     
   String get token
          return _token;
        
   String get userId 
     return _userId;
     
   Future<void> signup(String email, String password) async 
     final url = Uri.parse(
       'https://...myurl...'
       );
     try 
       final response = await http.post(url,body: json.encode(
            
           'email': email,
           'password':password,
           'returnSecureToken': true,
           ,), );
        final responseData = json.decode(response.body);
        if(responseData['error'] != null)
          throw Exception();
        
        _token = responseData['idToken'];
        _userId = responseData['localId'];
    notifyListeners();
       catch (error) 
         throw error;
      
   Future<void> login(String email, String password) async 
     final url = Uri.parse( 'https://...myurl...' );
     try 
       final response = await http.post(
           url, 
           body: json.encode(
            
           'email': email,
           'password':password,
           'returnSecureToken': true,
           ,),);
       catch (error) 
         throw error;
      

这是 Ath 屏幕:

enum AuthMode  Signup, Login 

class AuthScreen extends StatelessWidget 
  static const routeName = '/auth';

  @override
  Widget build(BuildContext context) 
    final deviceSize = MediaQuery.of(context).size;
    bool _isLoading= false;
    return Scaffold(
      backgroundColor: Colors.pinkAccent[100],
      body: SizedBox(
        height: double.infinity,
        child: Stack(
          children: <Widget>[
           Container(
              padding: EdgeInsets.all(8),
              margin: EdgeInsets.all(8),


              child: Expanded(
                child: 
                SizedBox(
                  height: 280,
                                 ),
              ),
            ), 

            SingleChildScrollView(
              child: Container(
                height: deviceSize.height,
                width: deviceSize.width,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[

                SizedBox(
                height: 60,
                child: LogoBekery(
                  color1:Colors.white,
                  color2:Colors.white,
                  color3:Colors.white,
                  ),
      ),
                    
                 SizedBox(
                  child:  ImageSlideshow(
                   isLoop: true,
                    width: double.infinity,
              
                    height: 250,
              
                    initialPage: 0,
              
                    indicatorColor: Colors.pink,
              
                    indicatorBackgroundColor: Colors.grey,
              
                    children: [
                         
                      Image.asset(
                        'assets/images/logoA.png',
                        fit: BoxFit.fill,
                      ),
                      Image.asset(
                        'assets/images/logoB.png',
                        fit: BoxFit.fill,
                      ),
                      Image.asset(
                        'assets/images/logoC.png',
                        fit: BoxFit.fill,
                      ),
                      Image.asset(
                        'assets/images/logoD.png',
                        fit: BoxFit.fill,
                      ),
                    ],
              
                    onPageChanged: (value) 
                     // print('Page changed: $value');
                    ,
              
                    autoPlayInterval: 3000,
                  ),
      ),
                    
                    Flexible(
                      flex: deviceSize.width > 600 ? 2 : 1,
                    child: AuthCard(),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  

  void _submitAuthForm(
    String email,
    String password,
    String username,
    bool isLogin,
    BuildContext ctx,
  ) 
  async 
    UserCredential authResult;  


class AuthCard extends StatefulWidget 
  const AuthCard(
    Key key,
  ) : super(key: key);

  @override
  _AuthCardState createState() => _AuthCardState();


class _AuthCardState extends State<AuthCard> 
  final GlobalKey<FormState> _formKey = GlobalKey();
  AuthMode _authMode = AuthMode.Login;
  Map<String, String> _authData = 
    'email': '',
    'password': '',
  ;
  var _isLoading = false;
  final _passwordController = TextEditingController();

  Future<void> _submit() async
    if (!_formKey.currentState.validate()) 
      // Invalid!
      return;
    
    _formKey.currentState.save();
    setState(() 
      _isLoading = true;
    );
  
    try 
      if (_authMode == AuthMode.Login) 
         await Provider.of<Auth>(context, listen: false).login(
          _authData['email'] ,
          _authData['password'] );
        
         else 
         
       await Provider.of<Auth>(context, listen: false).signup(
          _authData['email'] ,
          _authData['password'] );
      
      Navigator.of(context).pushReplacementNamed(ProductOverviewScreen.routeName);
     on Exception catch (error) 
        var errorMsg = 'Authentification Failed!';
     catch (error)
        var errorMsg = 'Could not authentificate! please try later...';

     
    setState(() 
      _isLoading = false;
    );
  

  void _switchAuthMode() 
    if (_authMode == AuthMode.Login) 
      setState(() 
        _authMode = AuthMode.Signup;
      );
     else 
      setState(() 
        _authMode = AuthMode.Login;
      );
    
  

  @override
  Widget build(BuildContext context) 
    final deviceSize = MediaQuery.of(context).size;
    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10.0),
      ),
      elevation: 8.0,
      child: Container(
        height: _authMode == AuthMode.Signup ? 320 : 260,
        constraints:
            BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 150 : 260),
        width: deviceSize.width * 0.8,
        padding: EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                TextFormField(
                  decoration: InputDecoration(labelText: 'E-Mail'),
                  keyboardType: TextInputType.emailAddress,
                  validator: (value) 
                    if (!RegExp(r'\S+@\S+\.\S+').hasMatch(value)) 
                      return 'Invalid email!';
                    
                    return null;
                    return null;
                  ,
                  onSaved: (value) 
                    _authData['email'] = value;
                  ,
                ),
                TextFormField(
                  decoration: InputDecoration(labelText: 'Password'),
                  obscureText: true,
                  controller: _passwordController,
                  validator: (value) 
                    if (value.isEmpty || value.length < 5) 
                      return 'Password is too short!';
                    
                  ,
                  onSaved: (value) 
                    _authData['password'] = value;
                  ,
                ),
                if (_authMode == AuthMode.Signup)
                  TextFormField(
                    enabled: _authMode == AuthMode.Signup,
                    decoration: InputDecoration(labelText: 'Confirm Password'),
                    obscureText: true,
                    validator: _authMode == AuthMode.Signup
                        ? (value) 
                            if (value != _passwordController.text) 
                              return 'Passwords do not match!';
                            
                          
                        : null,
                  ),
                SizedBox(
                  height: 20,
                ),
                if (_isLoading)
                  CircularProgressIndicator()
                else
                  RaisedButton(
                    child:
                        Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
                    onPressed: _submit,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(30),
                    ),
                    padding:
                        EdgeInsets.symmetric(horizontal: 30.0, vertical: 8.0),
                    color: Theme.of(context).primaryColor,
                    textColor: Theme.of(context).primaryTextTheme.button.color,
                  ),
                FlatButton(
                  child: Text(
                      '$_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN''),
                  onPressed: _switchAuthMode,
                  padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4),
                  materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                  textColor: Theme.of(context).primaryColor,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  

【问题讨论】:

身份验证状态会自动保持,因此您检测当前用户的方式可能存在一些问题。但是如果没有看到minimal code that reproduces the problem,就很难提供帮助。 我已经添加了我的代码的 auth 部分 如何检查用户是否登录? @PeterO。短期内是使用这个 mth try if (_authMode == AuthMode.Login) await Provider.of(context, listen: false).login( _authData['email'] , _authData['password'] ) ; else await Provider.of(context, listen: false).signup( _authData['email'] , _authData['password'] ); Navigator.of(context).pushReplacementNamed(ProductOverviewScreen.routeName); on Exception catch (error) var errorMsg = 'Failed!'; catch (error) var errorMsg = 'error'; 没找到你吗? 【参考方案1】:

您的_token_userId 仅在注册后设置。登录后不设置。因此token可能为null,isAuth会返回false。

我认为你应该在登录功能之后设置_token_userId的值。

Future<void> login(String email, String password) async 
  final url = Uri.parse('https://...myurl...');
  try 
    final response = await http.post(
      url,
      body: json.encode(
        
          'email': email,
          'password': password,
          'returnSecureToken': true,
        ,
      ),
    );
    // added from here
    final responseData = json.decode(response.body);
    if (responseData['error'] != null) 
      throw Exception();
    
    _token = responseData['idToken'];
    _userId = responseData['localId'];
    // to here.
   catch (error) 
    throw error;
  

【讨论】:

我应该从注册中删除它还是在登录时添加它? 添加到登录。我分享的代码就是一个例子。试试看。 我试过了,但没用 我不确定,但我认为我有一个带有我的令牌的 pb,它已过期,所以 p 可能是来自 firebase 的表单,但不知道如何处理

以上是关于当我在标签之间导航时自动注销问题(Firebase Auth rest API)的主要内容,如果未能解决你的问题,请参考以下文章

当我在firebase上删除他的帐户时如何从应用程序中注销用户?

注销后,身份验证firebase会记住我

扑火firebase谷歌退出不工作

Firebase - 重新打开应用程序后用户注销时应用程序关闭

导航控制器注销

如何使用firebase auth android无法返回android