如何在flutter中存储Cookies并使用它来验证用户是否登录



我正在尝试创建一个平台,一旦我登录它,创建一个令牌并将其存储在cookie中。我已经成功地使用node js创建了一个存储cookie的路由(我可以看到它保存在postman中)。但是当我尝试在我的flutter应用程序中使用这条路线时,似乎令牌没有保存到任何地方。

如何保存cookie并使用它来验证用户是否应该登录或应该再次登录

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;

输入图片描述

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

在api上创建授权端点,以便在令牌过期时刷新。在dart端,创建一个身份验证的客户端单例。

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);
}
}

在您的api上,对loginsignup请求生成令牌并发送令牌给客户端。对于本例,响应格式为:

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

得到响应后,调用AuthenticatedClientsetParams方法,设置请求参数。我没有在示例中添加错误处理代码,不要忘记添加。

使用AuthenticatedClient:

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

最新更新