简体   繁体   中英

How to store Cookies in flutter and use it to authenticate if user is logged in or not

I'm trying to create a platform, once I log in it, creates a token and store it in the cookie. I have successfully been able to create a route that stores the cookie using node js(I could see it saved in postman). But once I try to use the route in my flutter app, it seems the the token doesn't save anywhere.

How do I save the cookie and use it to validate if the user should be logged in or should log in again

Login.dart

Future<void> _signIn(email, password) async {
    try {
      setState(() {
        LoadingWidget.show(context);
        bool _absorbme = true;
      });

      var url = "http://192.168.8.23:3000/route/login"; // iOS
      final http.Response response = await http.post(
        Uri.parse(url),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(<String, String>{
          'email': email.toLowerCase(),
          'password': password,
        }),
      );

      SharedPreferences prefs = await SharedPreferences.getInstance();
      var parse = jsonDecode(response.body);
      await prefs.setString('msg', parse["msg"]);
      await prefs.setString('success', parse["success"]);
      String? msg = prefs.getString("msg");

    } finally {
      setState(() {
        LoadingWidget.hide(context);
        bool _absorbme = false;
      });
    }
  }

My Route.js file

const express = require('express');
const router = express.Router();
const Users = require('./model/model')
const passport = require('passport')
const bcrypt = require("bcrypt");
const { createTokens, validateToken, authenticateToken } = require("./JWT");
const Server = require('http-proxy');
router.get('/', (req, res)=>{
  res.send('Hello world')
})

router.post("/signup", async (req, res) =>  {

  const { username, email, password } = req.body;
  let user = await Users.findOne({ email });

  if (user){ 
    
    return res.status(400).json({success: 'false', msg: "Email Already Exist"});
  }
  bcrypt.hash(password, 10).then((hash) => {
    Users.create({
      username: username,
      password: hash,
      email:email,
    })
      .then(() => {
        res.json({success: 'true', msg: 'login Successfully'});
      })
      .catch((err) => {
        if (err) {
          res.status(400).json({success: 'false', msg: 'Failed to save'});
        }
      });
  });
});

router.post("/login", async (req, res) => {
  const { email, password } = req.body;

  let user = await Users.findOne({ email });

  if (!user) {
    
    return res.status(400).json({success: 'false', msg: 'Authentication Failed, User not found'});
  }

  const dbPassword = user.password;
  bcrypt.compare(password, dbPassword).then((match) => {
    if (!match) {
      res
        .status(400)
        .json({success: 'false',  msg: 'Authentication failed, wrong password'});
    } else {
      const accessToken = createTokens(user);

      var token = res.cookie("access-token", accessToken, {
        maxAge: 60 * 60 * 24 * 30 * 1000,
        httpOnly: true,
      });
      
      res
        .status(200)
        .json({success: 'true',  msg: 'Successfully logged In'});
    }
  });
});

router.get("/profile", validateToken, async (req, res) => {
 let user = await Users.findOne({email: req.decoded.email});
 return res.json({
   email: user.email, 
   balance: user.balance,
   name: user.username
})


router.get("/logout", validateToken, (req, res) => {
  return res
    .clearCookie("access-token")
    .status(200)
    .json({success: "true" , msg: "Successfully logged out" });
});

router.get("/authenticate" ,authenticateToken, (req,res)=>{

})


  module.exports = router;

enter image description here

为什么不使用 JWT 它可以帮助您在指定的小时数内管理用户

Create authorize endpoint on your api to refresh token when expired. In dart side, create an authenticated client singleton.

class AuthenticatedClient extends http.BaseClient {
  factory AuthenticatedClient() => _instance;
  AuthenticatedClient._();

  static final _instance = AuthenticatedClient._();

  int? expiresAt;
  String? token;
  final _client = http.Client();

  void setParams(http.Response res) {
    final response = jsonDecode(res.body);

    expiresAt = response['expiresAt'];
    token = response['token'];
  }

  Future<void> authorize() async {
    // Send a request to refresh token, update token and expiresAt
    // accordingly. Note that, you can't use _client to send request, use 
    // htt.put, http.post.
    // Ex:
    //
    // final response = await http.put(
    //  Uri.parse('https://myapi.com/authorize'),
    //  headers: {
    //    'Content-Type': 'application/json',
    //  },
    //  body: jsonEncode({
    //    'email': <email>,
    //    'password': <password>,
    //  }),
    // );
    //
    // setParams(response);
  }

  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) async {
    // Ensure you set params for the first time.
    assert(expiresAt != null);

    if (expiresAt! < DateTime.now().millisecondsSinceEpoch) {
      await authorize();
    }

    request.headers['Authorization'] = 'Bearer $token';

    return _client.send(request);
  }
}

On your api, generate a token on login or signup request and send token to client. For this example, response format is that:

{
  'token': <generated token>,
  'expiresAt': <timestamp>,
}

When you got response, call setParams method of AuthenticatedClient and set request params. I didn't add code for error handling to the example, don't forget to add.

Use AuthenticatedClient like this:

AuthenticatedClient().get(Uri.parse('https://myapi/profile'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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