随机重定向

时间:2018-01-17 14:29:54

标签: javascript node.js express

我的项目有问题。我想为图片制作一个小的下载系统,所以我为Dim vPath As String vPath = GetNewestDocument(Me!artNr) 'Returns path for pdf file, about:blank if there is no file. If vPath = "about:blank" Then Me!PDFBrowser.visible = True Me.PDFBrowser.SourceDoc = vbNullString Else With Me.PDFBrowser .OLETypeAllowed = acOLELinked .SourceDoc = vPath .SizeMode = acOLESizeStretch End With End If 制作了一个路由器。我有/download/:filename中的图片,如果我请求/下载/使用像/userdata/${userId}/这样的参数,它会在我的控制台中登录,但如果我使用了像test这样的用户数据文件夹中存在的参数它将我重定向回用户的主路径:/ file / $ {userId}这里是我的代码:

app.js

Download.jpg

index.js路由器

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
const admin = require("./routes/admin");
import file from "./routes/file";
import download from "./routes/download";
const session = require("express-session");
var app = express();
app.set("trust proxy", 1);
app.use(session({
  secret: "bla",
  resave: false,
  cookie: {
    maxAge: 120000000
  },
  saveUninitialized: false
}));
function checkIfLoggedin(req,res,next){
  if(!(req.originalUrl === "/") && !req.session.loggedIn){
    res.redirect('/');
    return;
  }
  next();
};

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(checkIfLoggedin);
app.use('/', index);
app.use("/admin", admin);
app.use("/file", file);
app.use("/download", download);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
module.exports = app;

file.js

var express = require('express');
var router = express.Router();
const bcrypt = require('bcrypt-nodejs');
var dbPassword;
import mysql from "mysql";
//
/* GET home page. */
router.get('/', function(req, res, next) {
  if (req.session.user != undefined) {
    res.redirect("/file/"+req.session.user.userId);
  }
  else{
    res.render('index', {});
  }
});
router.post('/', function(req,res,next) {
  console.log("1");
  const enteredUsername = req.body.username;
  const enteredPassword = req.body.password;
  const con = mysql.createConnection({
    host: "localhost",
    user: "user",
    password: "pass",
    database: "db"
  });
  con.query('SELECT * FROM users WHERE username = ?;', [`${enteredUsername}`], (error, results, fields) => {
    if (results.length > 0) {
      console.log("2");
      console.log(error);
      let dbPassword = results[0].password;
      bcrypt.compare(enteredPassword, dbPassword, (err,response) => {
        console.log(err);
        console.log(response);
        console.log("3");
        if (response == true) {
          req.session.user = {
            userId: results[0].userId,
            username: results[0].username,
            isAdmin: results[0].isAdmin,
          };
          req.session.loggedIn = true;
          console.log("file");
          if (req.session.user.isAdmin) {
            res.redirect("/admin");
          }
          else{
            res.redirect("/file/" + req.session.user.userId);
          }

        }
        else{
          req.session.loggedIn = false;

          console.log("false");
          res.send("Falsches Passwort");
        }
      });
    }
    else{
      res.send("Falsche Daten");
    }
  });
});
router.get("/logout", (req,res,next) => {
  if (req.session.user.userId) {
    req.session.destroy();
    res.redirect("/");
  }
});
module.exports = router;

download.js

import express from "express";
import fs from "fs";
const router = express.Router();
const userDataPath = "/srv/www/www.precode.tech/www/userdata/";
router.get("/:userId", (req,res,next) => {
  //console.log(req.params.userId == req.session.user.userId);
  if (req.params.userId == req.session.user.userId) {
    const userDataFiles = fs.readdirSync(userDataPath+req.session.user.userId);
    res.render("file", {files : userDataFiles, user: req.session.user});
  }
  else{
    res.status(403).render("unauthorized");

  }
  //res.send(`${req.params.userId} ${req.session.user.userId}`);
});
/*router.get("/:userId/download/:filename", (req,res,next) => {
  console.log(req.params.filename);
  if (req.params.userId == req.session.user.userId) {
    let filePath = `${__dirname}/../userdata/${req.session.user.userId}/`;
    res.download(filePath, req.params.filename);
    next();
  };
});*/
export default router;

如果您有想法或看到问题,那将是非常好的。 谢谢:))

编辑:它不应该重定向到用户的基本路径,下载的get请求应该总是在console.log项目

1 个答案:

答案 0 :(得分:0)

我没有找到这个缺陷,但让我们清理代码并修复中间件附加序列(至少我看到会话中间件后附加的cookie解析器,我怀疑只有那部分)并检查。

但是,让我们检查我的代码审查/清理。

真的希望它有所帮助。

app.js

const express = require('express');
const path = require('path');
//const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require("express-session");

const mysql = require('mysql');
const db = mysql.createConnection({
  host: "localhost",
  user: "user",
  password: "pass",
  database: "db"
});

const app = express();

app.set("trust proxy", 1);

// set view engine and renderer
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// serve static files
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); // no need for it since express static will serve all static files in public folder
app.use(express.static(path.join(__dirname, 'public')));

// connect morgan to profile requests
app.use(logger('dev'));

// parse cookies first
app.use(cookieParser());

// then handle session
app.use(session({
  secret: "bla",
  resave: false,
  cookie: {
    maxAge: 120000000
  },
  saveUninitialized: true
}));

// handle requests data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use((req, res, next) => {
  req.db = db; // attach db connection to request context
  next();
});

// public routes that does not need auth check
app.use('/', require('./routes/index'));

const checkIfLoggedin = (req, res, next) => {
  if (!req.session.loggedIn) {
    return res.redirect('/');
  }
  res.locals.user = req.session.user;
  next();
};

// internal routes that needs auth check
app.use(
  '/admin', 
  checkIfLoggedin, 
  require('./routes/admin'));

app.use(
  '/files', 
  checkIfLoggedin, 
  require('./routes/files'));

/* no need for this route, it's covered in files.js
app.use(
  '/download', 
  checkIfLoggedin,
  download);
*/

// catch 404 and forward to error handler
app.use((error, req, res, next) => {
  if (error) return next(error);


  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use((error, req, res, next) => {
  // set locals, only providing error in development
  res
   .status(error.status || 500)
   .render('error', {
     message: error.message,
     error: req.app.get('env') === 'development' ? error : {}
   });
});

module.exports = app;

routes/index.js

const express = require('express');
const router = express.Router();
const logger = require('winston');
const bcrypt = require('bcrypt-nodejs');
const _ = require('lodash'); // install it:  npm i --save lodash

/* GET home page. */
router.get('/', (req, res) => {
  if (_.get(req, 'session.user.userId')) {
    return res.redirect("/files/" + req.session.user.userId);
  }

  res.render('index', {});
});


router.post('/auth', (req, res, next) => {
  const {username, password} = req.body;

  const db = req.db;
  const query = 'SELECT * FROM users WHERE username = ? LIMIT 1';
  const fields = [username];
  db.query(
    query,
    fields,
    (err, result) => {
      if (err) {
        logger.error(err);
        const error = new Error('System fehler');
        return next(error);
      }

      const user = _.get(result, '0');

      if (!user) {
        req.session.loggedIn = false;
        const error = new Error('Benutzer nicht gefunden');
        error.status = 403;
        return next(error);
      }

      bcrypt.compare(password, user.password,
        (err, isEqual) => {
          if(err || !isEqual) {
            if (err) logger.error('Error in password compare:', err);
            const error = new Error('Passwort ungültig');
            error.status = 403;
            return next(error);
          }


          req.session.user = _.pick(user, ['id', 'userId', 'username', 'isAdmin']);
          req.session.loggedIn = true;

          if (user.isAdmin) {
            return res.redirect("/admin");
          }

          res.redirect("/files/" + user.userId);

        });
    });
});


router.get("/logout", (req, res) => {
  // simply destroy session and redirect, 
  // no need for session check
  req.session.destroy();
  res.redirect("/");
});

module.exports = router;

routes/files.js

const express = require('express');
const router = express.Router();
const logger = require('winston');
const fs = require('fs');
const path = require('path');
const async = require('async');

const userDataPath = path.join(__dirname, '..', 'userdata');

// no need to check userId with session.user.userId 
// since middleware attached in app.js will guard this route 
// and redirect user to '/'

router.get('/:userId', (req, res, next) => {
  if(req.params.userId != req.session.user.userId) {
    const error = new Error("You cannot access other user's files");
    error.status = 403;
    return next(error);
  }

  const directory = path.join(userDataPath, req.params.userId);
  logger.info('Reading directory:', directory);
  fs.readdir(
    directory, 
    (err, entries) => {
      if (err) {
        logger.error(err);
        const error = new Error('System error');
        return next(error);
      }

      const directories = [];
      const files = [];
      async.eachLimit(
        entries, 10, 
        (entry, done) => {
          fs.stat(path.join(dir, entry), (error, stat) => {
            if (stat.isFile()) files.push(entry);
            if (stat.isDirectory()) directories.push(entry);
            done();
          });
        },
        () => {
          res.render("files", {
            directories,
            files
          });
        });          
    });
});

router.get('/:userId/download/:filename', (req, res, next) => {
  if(req.params.userId != req.session.user.userId) {
    const error = new Error("You cannot access other user's files");
    error.status = 403;
    return next(error);
  }
  res.download(path.join(userDataPath, req.params.userId, req.params.filename));
});

module.exports = router;

P.S。如果它在nginx,apache等后面工作,请确保无法公开访问userdata文件夹。