且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

flutter firebase 使用 refreshToken 自动刷新用户会话

更新时间:2023-12-06 08:43:10

我编辑了你的 refresh_token() 函数.

I edited your refresh_token() function.

首先,您应该在带有链接的 firebase 项目中使用您的 web api 密钥.您还应该保存刷新令牌.如果你像这样发布,它会起作用.如果不起作用,请尝试在我提交时在您的身体上不使用 json.encode() 函数.

Firstly, you should use your web api key on your firebase project with the link. You should also save the refresh token. And if you post like this, it will work. If don't work, try without json.encode() function on your body as I commit.

Future<void> refreshSession() async {
  final url =
      'https://securetoken.googleapis.com/v1/token?key=$WEB_API_KEY'; 
  //$WEB_API_KEY=> You should write your web api key on your firebase project.
  
  try {
    final response = await http.post(
      url,
      headers: {
        "Accept": "application/json",
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: json.encode({
        'grant_type': 'refresh_token',
        'refresh_token': '[REFRESH_TOKEN]', // Your refresh token.
      }),
      // Or try without json.encode.
      // Like this:
      // body: {
      //   'grant_type': 'refresh_token',
      //   'refresh_token': '[REFRESH_TOKEN]',
      // },
    );
    final responseData = json.decode(response.body);
    if (responseData['error'] != null) {
      throw HttpException(responseData['error']['message']);
    }
    _token = responseData['id_token'];
    _refresh_token = responseData['refresh_token']; // Also save your refresh token
    _userId = responseData['user_id'];
    _expiryDate = DateTime.now()
        .add(Duration(seconds: int.parse(responseData['expires_in'])));
    _autoLogout();

    notifyListeners();

    final prefs = await SharedPreferences.getInstance();
    final userData = json.encode({
      'token': _token,
      'refresh_token': _refresh_token,
      'userId': _userId,
      'expiryDate': _expiryDate.toIso8601String(),
    });
    prefs.setString('userData', userData);
  } catch (error) {
    throw error;
  }
}


这是我编辑过的完整 auth.dart 文件.


This is your full auth.dart file which I edited.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../provider/http_exception.dart';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';

class Auth with ChangeNotifier {
  String _token;
  String _refresh_token;
  DateTime _expiryDate;
  String _userId;
  Timer _authTimer;
  bool wasLoggedOut = false;
  bool onBoarding = false;

  Future<void> createUser(String email, String firstName, String lastName) async {
    final url = 'https://test45.firebaseio.com/users/$userId.json?auth=$token';
    final response = await http.put(url, body: json.encode({
      'userEmail': email,
      'userIsArtist': false,
      'userFirstName': firstName,
      'userLastName': lastName,
    }));
    print('post ist done');
    print(json.decode(response.body));
  }

  bool get isAuth {
    return token != null;
  }

  String get userId {
    return _userId;
  }

  String get token {
    if (_expiryDate != null &&
        _expiryDate.isAfter(DateTime.now()) &&
        _token != null && _refresh_token!=null) {
      return _token;
    }
    refreshSession();
    return null;
  }

  Future<void> authenticate(
      String email, String password, String urlSegement) async {
    final url = 'https://identitytoolkit.googleapis.com/v1/accounts:$urlSegement?key=AIzaSyD8pb3M325252dfsDC-4535dfd';

    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 HttpException(responseData['error']['message']);
      }
      _token = responseData['idToken'];
      _refresh_token = responseData['refreshToken'];
      _userId = responseData['localId'];
      _expiryDate = DateTime.now().add(Duration(seconds: int.parse(responseData['expiresIn'])));
      _autoLogout();
     
      notifyListeners();

      final prefs = await SharedPreferences.getInstance();
      final userData = json.encode({
        'token': _token,
        'refresh_token': _refresh_token,
        'userId': _userId,
        'expiryDate': _expiryDate.toIso8601String(),
      });
      prefs.setString('userData', userData);
    } catch (error) {
      throw error;
    }
  }

  Future<void> signup(String email, String password) async {
    return authenticate(email, password, 'signUp');
  }

  Future<void> signin(String email, String password) async {
    return authenticate(email, password, 'signInWithPassword');
  }

  Future<bool> tryAutoLogin() async {
    final prefs = await SharedPreferences.getInstance();
    if(!prefs.containsKey('userData')){
      return false;
    }
    final extractedUserData = json.decode(prefs.getString('userData')) as Map<String, Object>;
    final expiryDate = DateTime.parse(extractedUserData['expiryDate']);

    if(expiryDate.isBefore(DateTime.now())) {
      return false;
    }

    _token = extractedUserData['token'];
    _refresh_token = extractedUserData['refresh_token'];
    _userId = extractedUserData['userId'];
    _expiryDate = expiryDate;

    notifyListeners();
    _autoLogout();
    return true;
  }


  Future<void> logout() async {
    _token = null;
    _refresh_token = null;
    _userId = null;
    _expiryDate = null;
    if(_authTimer != null){
      _authTimer.cancel();
      _authTimer = null;
    }
    notifyListeners();
    final prefs = await SharedPreferences.getInstance();
    prefs.remove('userData');
  }

  void _autoLogout() {
    if(_authTimer != null) {
      _authTimer.cancel();
    }
  final timetoExpiry =  _expiryDate.difference(DateTime.now()).inSeconds;
    _authTimer = Timer(Duration(seconds: timetoExpiry), logout);
  }
  
  


Future<void> refreshSession() async {
  final url =
      'https://securetoken.googleapis.com/v1/token?key=$WEB_API_KEY'; 
  //$WEB_API_KEY=> You should write your web api key on your firebase project.
  
  try {
    final response = await http.post(
      url,
      headers: {
        "Accept": "application/json",
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: json.encode({
        'grant_type': 'refresh_token',
        'refresh_token': '[REFRESH_TOKEN]', // Your refresh token.
      }),
      // Or try without json.encode.
      // Like this:
      // body: {
      //   'grant_type': 'refresh_token',
      //   'refresh_token': '[REFRESH_TOKEN]',
      // },
    );
    final responseData = json.decode(response.body);
    if (responseData['error'] != null) {
      throw HttpException(responseData['error']['message']);
    }
    _token = responseData['id_token'];
    _refresh_token = responseData['refresh_token']; // Also save your refresh token
    _userId = responseData['user_id'];
    _expiryDate = DateTime.now()
        .add(Duration(seconds: int.parse(responseData['expires_in'])));
    _autoLogout();

    notifyListeners();

    final prefs = await SharedPreferences.getInstance();
    final userData = json.encode({
      'token': _token,
      'refresh_token': _refresh_token,
      'userId': _userId,
      'expiryDate': _expiryDate.toIso8601String(),
    });
    prefs.setString('userData', userData);
  } catch (error) {
    throw error;
  }
}
}