mongodb 获取数据并将其存储在带有 Flutter 该高速缓存中

k10s72fa  于 2023-06-05  发布在  Go
关注(0)|答案(2)|浏览(416)

我正在用Flutter开发一个应用程序。在登录过程中,我正在检索数据。其想法是将此数据存储在该高速缓存中,并在以后用于其他操作。我使用nodejs,mongodb作为后端,flutter作为前端。我想在登录过程中检索专业化列表。一旦用户登录,就会创建令牌,并将userId、电子邮件和令牌等信息存储在cookie中。然后,我有一个中间件verifyAccessToken,它检查cookie中的令牌是否可用,如果检查正确,则API getSpecialization返回可用的专业化列表。我面临的问题是,我在flutter中的登录APIservice中包含getSpecialization,但我无法检索列表,因为verifyAccessToken中间件被绕过,导致403错误。任何帮助将不胜感激。下面是我的后端和前端代码:
Nodejs登录:

const authService = require("../../../services/authService");

exports.login = async (req, res, next) => {
    const { email, password } = req.body;
    console.log("login req body is ", req.body);
    //simple checker for username and password
    if (!email || !password) {
        return res.status(400).json({ message: "email or password is missing" });
    }

    try {
        //get the data from our auth service
        const { user, validPassword, token,  maxAge } = await authService.loginUser(email, password)
        //check if the user exists
        if (!user) {
            return res.status(401).json({
                message: "Login not successful",
                error: "User not found",
            });
        }
        //return error if the password is incorrect
        if (!validPassword) {
            return res.status(401).json({
                message: "Login not successful",
                error: "Password is incorrect",
            });
        }
        res.cookie("email", user.email, {
            httpOnly: true,
            maxAge: maxAge * 1000, // convert 2h to ms; maxAge uses milliseconds
          });

          res.cookie("userId", user._id,{
            httpOnly: true,
            maxAge: maxAge * 1000, // convert 2h to ms; maxAge uses milliseconds
          });
          
        //send our cookie with the token
        res.cookie("jwt", token, {
            httpOnly: true,
            maxAge: maxAge * 1000, //convert 2h to ms; maxAge uses miliseconds

        });

        //if everything is good return the user
        return res.status(200).json({
            message: "Login successful",
            user,
            
        });
       

    } catch (err) {
        res.status(401).json({
            message: "Login not successful",
            error: err.message,
        });
    }
};

verifyAccessToken:

const jwt = require("jsonwebtoken");
require("dotenv").config();

//this only works if you use cookie-parser
const checkCookie = (req) => {
    console.log('inside checkCookie')
    console.log('all our cookies are: ', req.cookies)
    //we get the jwt cookie we need
    return req.cookies['jwt']
}

//middleware for verifying the JWT
const verifyAccessToken = (req, res, next) => {
    //define token
    let token;

    //authenticate through Bearer token
    if (req.headers.authorization && req.headers.authorization.startsWith("Bearer ")) {
        token = req.headers.authorization.split(' ')[1]
        //logs so you see what's happening
        console.log('auth bearer token')
        console.log({ token })
    }
    else {
        token = req.headers["x-access-token"] || checkCookie(req) || null
        //logs
        console.log('our token is from x-access-token header, a cookie or null')
        console.log({ token })
    }

    //if we can't get our token anywhere then the response is an error
    if (!token) {
        return res.status(403).send("A token is required for authentication");
    }
    try {
        //we use the JWT library to verify the token
        //and we need to know the token_key which we encrypted our information
        const decoded = jwt.verify(token, process.env.TOKEN_KEY);
        //log
        console.log({ decoded })
        //the middleware adds the user information to the request and sends it to the route
        req.user = decoded;
    } catch (err) {
        return res.status(401).send("Invalid Token");
    }
    //if you have doubts check Express middleware docs: http://expressjs.com/en/guide/using-middleware.html
    return next();
};

module.exports = verifyAccessToken;

getSpecialization:

const {Specialization} = require('../../../models/specialization')

exports.getSpecialization = async (req, res) => {
    try {
      const specializzazioni = await Specialization.find({}, { _id: 0, __v: 0 }); // Escludi _id e __v dalla risposta
      res.json(specializzazioni);
    } catch (error) {
      console.error('Errore durante il recupero delle specializzazioni:', error);
      res.status(500).json({ message: 'Errore durante il recupero delle specializzazioni' });
    }
  };

路线

router.route("/login").post(login);

//router.use(verifyAccessToken);
router.use(verifyAccessToken);
router.route("/book").post(book);
router.route("/getbooking/:id").get(getBooking);
router.route("/logout").get(logout);
router.route("/getSpecialization").get(getSpecialization);

Flutter登录APIService

static Future<bool> login(LoginRequestModel model) async {
    Map<String, String> requestHeaders = {
      'Content-Type': 'application/json',
    };

    var url = Uri.http(Config.apiUrl, Config.loginAPI);

    var response = await client.post(url,
        headers: requestHeaders,
        body: jsonEncode(model.toJson())
    );

    if (response.statusCode == 200) {
      // Settare i dettagli del login
      await SharedService.setLoginDetails(loginResponseJson(response.body));

      // Ottenere il valore del cookie 'set-cookie' dalla risposta
      String? setCookie = response.headers['set-cookie'];

      if (setCookie != null) {
        // Estrarre il valore del token dal cookie
        String? token = parseCookieValue(setCookie);
        print (token);

        if (token != null) {
          SharedPreferences prefs = await SharedPreferences.getInstance();
          await prefs.setString('jwt', token);
        }
      }
      await getSpecializations();
      return true;
    } else {
      return false;
    }
  }

getSpecialization

static Future<List<Specialization>> getSpecializations() async {
    var url = Uri.http(Config.apiUrl, Config.getSpecializaionAPI);

    var response = await client.get(url);

    if (response.statusCode == 200) {
      // Converte la risposta JSON in una lista di oggetti Specialization
      List<dynamic> jsonList = jsonDecode(response.body);
      List<Specialization> specializations = jsonList
          .map((item) => Specialization(
        specId: item['specId'],
        description: item['description'],
      ))
          .toList();

      return specializations;
    } else {
      return []; // o gestisci l'errore in base alle tue esigenze
    }
  }
m0rkklqb

m0rkklqb1#

注1:

通过flutter获取数据并存储该高速缓存中

  • 有了这个,只需将您的访问令牌存储在本地数据库中(即,sqflite、sembast等)或共享首选项,且无论何时发出任何请求(如GET或POST),都应将访问令牌包含在 “client” 示例中。

示例:

Map<String, String> requestHeaders = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer $token',
  };

  var response = await client.get(url, headers: requestHeaders);

注2:

然后我有一个中间件verifyAccessToken,它可以检查cookie中的令牌是否可用

  • 这就是返回错误的那个。* “身份验证需要令牌”* 后者应该可以解决您的问题。

注3:

刷新访问令牌

  • 访问令牌可能会过期,因此在再次发出任何请求之前,请确保使用刷新令牌机制。在这种情况下,我们可以使用dio插件。

示例:

var payload = {
          'grant_type': 'refresh_token',
          'refresh_token': REFRESH_TOKEN,
          'client_id': CLIENT_ID,
          'client_secret': CLIENT_SECRET,
        };
    
      
          var response = await dio.post(url,
              data: payload,
              options: Options(contentType: Headers.formUrlEncodedContentType));
j5fpnvbx

j5fpnvbx2#

您面临的问题是getSpecialization API端点受verifyAccessToken中间件保护,但当您从Flutter登录过程调用它时,中间件被绕过,导致403错误。
要解决这个问题,您需要确保身份验证令牌与请求沿着发送到getSpecialization端点。以下是如何修改Flutter代码以包含令牌:
1.在Flutter登录APIService中修改getSpecializations方法,如下所示:

static Future<List<Specialization>> getSpecializations() async {
  var url = Uri.http(Config.apiUrl, Config.getSpecializaionAPI);

  SharedPreferences prefs = await SharedPreferences.getInstance();
  String? token = prefs.getString('jwt');

  Map<String, String> requestHeaders = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer $token',
  };

  var response = await client.get(url, headers: requestHeaders);

  if (response.statusCode == 200) {
    // Converte la risposta JSON in una lista di oggetti Specialization
    List<dynamic> jsonList = jsonDecode(response.body);
    List<Specialization> specializations = jsonList
        .map((item) => Specialization(
              specId: item['specId'],
              description: item['description'],
            ))
        .toList();

    return specializations;
  } else {
    return []; // o gestisci l'errore in base alle tue esigenze
  }
}

1.确保您已导入Flutter所需的包:

import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

通过将Authorization标头与从共享首选项中检索到的令牌一起包含在其中,可以确保将令牌与请求沿着发送到后端,从而允许verifyAccessToken中间件正确地对请求进行身份验证。
请注意,此解决方案假定您已经实现了登录过程,并将令牌存储在共享首选项中。如果您还没有实现它,请确保在成功登录后将令牌存储在共享首选项中。
通过这些修改,您应该能够在登录过程之后检索专门化列表,而不会遇到403错误。

相关问题