В настоящее время я работаю над своим первым проектом node.js / реагировать, и я sh хочу начать собственно использовать проект, но боюсь, что может быть какая-то критическая уязвимость, о которой я не знаю. Я получил сертификат SSL, поэтому мне не нужно об этом беспокоиться, я также запускаю HTTPS (когда могу) и использую библиотеку шлемов.
У меня есть два основных промежуточных ПО аутентификации, которые я создал, одно для большинства маршрутов, а второй - для маршрута загрузки файла. Мне понадобилось отдельное промежуточное программное обеспечение для этих двух типов маршрутов, потому что я хотел использовать встроенную загрузку файлов, которая поставляется с веб-браузерами (в основном он щелкает по невидимой ссылке, чтобы запустить GET-запрос на загрузку файла.), И нет хороший способ отправить токен авторизации с этим запросом (без использования куки, которых я бы хотел избежать). Из-за этого, как я заявляю в комментариях к кодам, я сделал так, чтобы клиенту сначала нужно было получить временный токен и отправить его, так как его безопаснее (надеюсь) использовать в URL, потому что я сразу отозвал этот токен после маршрута аутентифицируется через промежуточное программное обеспечение.
Я разместил код ниже (с комментариями), если бы мог получить некоторую информацию, которая будет принята с благодарностью:
// Default Auth middleware for routes
const jwt = require("jsonwebtoken");
const User = require("../models/user");
const env = require("../enviroment/env");
const auth = async(req, res, next) => {
try {
const token = req.header("Authorization").replace("Bearer ", "");
const decoded = await jwt.verify(token, env.password);
const user = await User.findOne({_id: decoded._id, "tokens.token": token})
if (!user) {
throw new Error("User not found")
}
req.token = token;
req.user = user;
} catch (e) {
console.log(e);
// Should I throw an error here? As i state below, I have custom error
// Objects I could throw instead. Or perhaps not wrap
// This in a try or catch at all, and throw the
// Error above?
res.status(401).send({error: "Error Authenticating"})
}
next();
}
module.exports = auth;
// Example of a controller
async getFileInfo(req, res) {
if (!req.user) {
return;
// Is this an anti-pattern? I have custom error objects
// Should I throw inside of auth instead of checking
// For user here?
}
try {
const fileID = req.params.id;
const userID = req.user._id;
const file = await fileService.getFileInfo(userID, fileID);
// The service/db utility also makes sure the userID matches the
// User._id of the currently authenticated user. So an authenticated
// User cannot get another users data.
res.send(file);
} catch (e) {
const code = e.code || 500;
// The customer error object appends an error
// Code to itself, if its not an error thrown
// It will use 500 as a default instead.
console.log(e);
res.status(code).send()
}
}
// Middleware auth for file downloading
const jwt = require("jsonwebtoken");
const User = require("../models/user");
const env = require("../enviroment/env");
const tempAuth = async(req, res, next) => {
try {
const token = req.params.tempToken;
// This middleware requires a tempToken to first be acquired,
// This is because I wish to use the built in browser
// Download for files, and I cannot send an auth
// Token when doing so (Without cookies, which i want to avoid).
const decoded = await jwt.verify(token, env.password);
const user = await User.findOne({_id: decoded._id, "tempTokens.token": token})
// The tempToken is appended through a separate request,
// That sends the tempToken to the client.
user.tempTokens = user.tempTokens.filter((filterToken) => {
return filterToken.token !== token
// I immediately remove this tempToken after the token is verified,
// Before the download even begins.
})
await user.save();
req.user = user;
req.auth = true;
} catch (e) {
console.log(e);
}
next();
}
module.exports = tempAuth;
// Controller For File Downloading
async downloadFile(req, res) {
if (!req.auth || !req.user) {
return await res.status(401).send("Please authenticate")
}
try {
console.log("download request")
const userID = req.user._id;
const fileID = req.params.id;
await fileService.downloadFile(userID, fileID, res);
} catch (e) {
const code = e.code || 500;
const message = e.message || e;
console.log(message, e);
res.status(code).send();
}
}
// Db Utility
this.getFileInfo = async(fileID, userID) => {
const file = await conn.db.collection("fs.files")
.findOne({"metadata.owner": userID, "_id": ObjectID(fileID)});
// I also make sure the owner matches up with the current userID
return file;
}
Примечание: Хотя я действительно хочу сделайте это приложение опубликованным c и с открытым исходным кодом на github в конце концов, я хочу подключиться только к своему домашнему веб-серверу (я размещаю этот сервер у себя дома и не использую какой-либо облачный сервис, я хотел сохранить все большие файлы загружаются локально.). Из-за этого внутри файла env я сделал возможность отключить создание учетной записи, поэтому после того, как я создал свою учетную запись, я активировал ее, создание учетной записи также запрещено на стороне сервера.