Я подробно расскажу о том, что я действительно хочу, чтобы мой сервер делал. Итак, я создаю проект, в котором пользователь регистрируется, а затем входит в систему.
Маршруты такие - localhost:3000/login
и localhost:3000/register
Теперь, когда пользователь входит в систему, используя свои учетные данные (POST), он должен отправить их на localhost:3000/home
, который уникален для каждого человека. Я не хочу отправлять данные, как мы это делаем для механизмов шаблонов, но я хочу сделать эти данные доступными по всем маршрутам, чтобы я мог использовать их, когда захочу.
У меня проблемы с тем, что когда человек входит в систему, его данные сохраняются в сеансе (который содержит его имя и другие пользовательские данные), который на данный момент не может использоваться между маршрутами. Сеанс сохраняется для маршрута /login
, и я не могу использовать его для маршрута /home
или для любого другого маршрута в этом отношении.
Есть ли способ, которым я могу использовать сохранение сеанса каждый раз, когда человек входит в систему (используя POST), и сделать эти данные сеанса доступными для всех моих маршрутов?
сервер.js
var express = require('express');
const path = require('path');
const fs = require('fs');
const session = require('express-session');
const { v4: uuidv4 } = require('uuid');
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public/auth-pages')));
app.use(express.json());
var publicPath = __dirname+"/public"
var authPagesPath = publicPath+"/auth-pages"
var jsonPath = __dirname+"/json"
var usersFile = jsonPath+"/users.json"
var testVar = 1;
app.set('view engine', 'pug')
// have to be on top
app.use(logger)
app.get('/',(req,res) => {
res.sendFile('index.html',{root:publicPath})
})
app.get('/home',(req,res) => {
var data = {}
res.render('home',data)
})
app.get('/profile',(req,res) => {
var data = {}
res.render('profile',data)
})
app.get('/login',(req,res) => {
res.sendFile('login.html',{root:authPagesPath})
})
app.get('/register',(req,res) => {
res.sendFile('register.html',{root:authPagesPath})
})
app.post('/register',(req,res) => {
var data = req.body;
if (register(data)){
res.send({
register:"success"
})
}
else {
res.send({
register:"fail"
})
}
})
app.post('/login',(req,res) => {
var data = req.body;
fs.readFile(usersFile,(error,fullData) => {
var fullData = JSON.parse(fullData);
allUsernames = Object.keys(fullData);
if (!allUsernames.includes(data.username)){
res.send({
login:"fail",
reason:"invalid-username"
})
}
else if (fullData[data.username]['pwd'] != data.pwd){
res.send({
login:"fail",
reason:"wrong-pwd"
})
}
else {
res.send({
login:"success",
user:fullData[data.username]
})
// session storage
req.session.user = {
username:data.username,
id:fullData[data.username]['id']
}
console.info(req.session)
}
})
})
app.get('/test',(req,res) => {
testVar += 1;
res.send(""+testVar);
})
function register(data){
fs.readFile(usersFile,(err,fullData) => {
var fullData = JSON.parse(fullData)
if (Object.keys(fullData).includes(data.username)){
console.info('username taken')
}
else {
fullData[data.username] = {
id:uuidv4(),
pwd:data.pwd
}
fullData = JSON.stringify(fullData,null,4)
fs.writeFile(usersFile,fullData,error => {
})
}
})
return true;
}
Вы можете использовать файлы cookie для хранения пользовательских данных между маршрутами.
Если вы не хотите хранить все данные в браузере, вы можете сохранить идентификатор пользователя в файлах cookie и хранить все данные в объекте репозитория.
например: вы можете создать класс, который будет хранить состояние вошедших в систему пользователей и может быть доступен между маршрутами. класс должен быть создан, и вы должны экспортировать его объект.
(это решение сохраняет состояние в памяти и будет потеряно при перезапуске/отключении службы. Чтобы сделать состояние доступным после перезапуска, вы можете сохранить состояние в БД (redis, mongo и т. д.)).
класс репо:
class MyRepository {
constuctor() {
this.users = {};
}
set(user) {
this.users[user.id] = user;
}
get(userId) {
return this.users[userId];
}
}
let repo = new MyRepository();
module.exports = repo;
маршрут:
const express = require('express');
const router = express.Router();
const repo = require('myrepository.js'); // this line will get you the object with all logged in users already
router.post('/login', (req, res, next) => {
// check if user logged in and get the user id (to myUserId);
user = ...
logged = ...
if (logged) {
res.cookie('userId', user.id)
repo.set(user)
}
});
route.get('/home', (req, res, next) => {
let userId = req.cookies.userId // get user id from cookie
let user = repo.get(userId);
});
Вы можете сделать это, имея какой-то класс, который содержит данные пользователя. Имейте в виду, что это решение не масштабируется, и вы создаете единую точку отказа.
Например, если у вас есть несколько серверов, на которых запущено ваше приложение, с балансировщиком нагрузки, который направляет запросы на ваши серверы. Допустим, сервер А создает объект из класса для пользователя А. Во втором или третьем запросе предположим, что запрос пользователя А направляется на сервер Б, который не создал объект, содержащий данные пользователя А. Это приводит к проблемам масштабируемости и даже, возможно, к проблемам несогласованности.
Что мешает вам использовать сеанс на других маршрутах?