как защитить общедоступную динамическую папку в nodejs

я показываю фотографии с нефритом в public/images/picture.jpg, но я хочу защитить некоторые фотографии или ограничить доступ к общей папке, как это сделать??

project
    node_modules
    public
        images
            image.jpg
        javascripts
        stylesheets
        protected_folder*
            image_protected.jpg
    views

person andrescabana86    schedule 11.08.2012    source источник
comment
Как насчет изменения разрешения файла, если вы находитесь на сервере Linux.   -  person Bharat    schedule 11.08.2012


Ответы (1)


Примечание: для всех этих примеров я использую приложение со следующей структурой:

.
├── app.js
└── public
    ├── protected
    │   └── file.txt  <-- contains text "protected file"
    └── regular
        └── file.txt  <-- contains text "regular file"

У вас есть несколько вариантов. Самый простой способ — заставить Express направить запрос через ваш маршрутизатор перед общедоступным промежуточным программным обеспечением, что позволит вам перехватить запрос:

var express = require('express');
var http = require('http');
var path = require('path');

var app = express();

// use app.router before express.static
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

function userIsAllowed(callback) {
  // this function would contain your logic, presumably asynchronous,
  // about whether or not the user is allowed to see files in the
  // protected directory; here, we'll use a default value of "false"
  callback(false);
};

app.get('/', function(req, res, next) {
  res.end('Home page');
});

app.get('/protected/*', function(req, res, next) {
  userIsAllowed(function(allowed) {
    if (allowed) {
      next(); // call the next handler, which in this case is express.static
    } else {
      res.end('You are not allowed!');
    }
  });
});

http.createServer(app).listen(3000, function(){
  console.log('Express server listening on port 3000');
});

Полученные результаты:

http://localhost:3000/regular/file.txt # regular file
http://localhost:3000/protected/file.txt # You are not allowed!

Проблема с этим подходом заключается в том, что запрос должен пройти весь путь через маршрутизатор вашего приложения, прежде чем статический файл может быть обслужен, что не так эффективно, но может подойти для ваших нужд (вам нужно будет принять некоторые замеры и узнайте сами).


Другой вариант — вставить небольшую функцию в цепочку промежуточного программного обеспечения, которая делает в основном то же самое, но не требует прохождения через весь маршрутизатор приложения:

var express = require('express');
var http = require('http');
var path = require('path');

function userIsAllowed(callback) {
  // this function would contain your logic, presumably asynchronous,
  // about whether or not the user is allowed to see files in the
  // protected directory; here, we'll use a default value of "false"
  callback(false);
};

// This function returns a middleware function
var protectPath = function(regex) {
  return function(req, res, next) {
    if (!regex.test(req.url)) { return next(); }

    userIsAllowed(function(allowed) {
      if (allowed) {
        next(); // send the request to the next handler, which is express.static
      } else {
        res.end('You are not allowed!');
      }
    });
  };
};

var app = express();

app.use(protectPath(/^\/protected\/.*$/));
app.use(express.static(path.join(__dirname, 'public')));

app.get('/', function(req, res, next) {
  res.end('Home page');
});

http.createServer(app).listen(3000, function(){
  console.log('Express server listening on port 3000');
});

Это выполняет в основном ту же логику, но вместо того, чтобы направлять каждый запрос через весь маршрутизатор приложения, он запускает небольшую функцию в начале каждого запроса, которая проверяет, соответствует ли запрошенный URL-адрес регулярному выражению, которое вы передан. Если это так, он запускает проверку, чтобы увидеть, может ли пользователь получить доступ к файлу.

Полученные результаты:

http://localhost:3000/regular/file.txt # regular file
http://localhost:3000/protected/file.txt # You are not allowed!
person Michelle Tilley    schedule 11.08.2012
comment
это работает ... но как подать заявку, чтобы разрешить только загрузку, а не изменять или загружать каталог ... - person andrescabana86; 12.08.2012
comment
Я не уверен, что ты имеешь в виду; как пользователь сможет изменить каталог в первую очередь? - person Michelle Tilley; 12.08.2012
comment
Вы имеете в виду, как применить защиту только к запросам GET, а не POST или PUT? Вы можете проверить, есть ли req.method == 'GET' (вы также можете защитить запросы 'HEAD'). - person Michelle Tilley; 12.08.2012
comment
мой плохой ... это ответ, спасибо - person andrescabana86; 13.08.2012
comment
Спасибо за это. Провел утро, просматривая этот материал, и теперь он хорошо настроен благодаря этому посту. - person CargoMeister; 01.02.2014
comment
Является ли это допустимым решением для последней версии Node.js? Хотя бы строчка: app.use(app.router); устарело. Без него это решение не работает. - person Waltari; 06.11.2016
comment
В моем случае он не входит внутрь app.get по пути вида domain.com/protected/1.jpg Он проходит внутри app.get только по пути типа domain.com/protected или domain.com/protected - person deepmoteria; 07.12.2016