Экспресс res.sendfile бросает запрещенную ошибку

160

У меня есть этот код:

res.sendfile( '../../temp/index.html' )

Тем не менее, он выдает эту ошибку:

Error: Forbidden
at SendStream.error (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/send/lib/send.js:145:16)
at SendStream.pipe (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/send/lib/send.js:307:39)
at ServerResponse.res.sendfile (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/response.js:339:8)
at exports.boot (/Users/Oliver/Development/Personal/Reader/server/config/routes.js:18:9)
at callbacks (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:161:37)
at param (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:135:11)
at pass (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:170:5)
at Object.router (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:33:10)
at next (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/connect/lib/proto.js:199:15)

Может кто-нибудь сказать мне, почему это может быть?


источник
3
Я верю, что это из-за относительного пути; «../» считается злонамеренным. Сначала разрешите локальный путь, затем позвонитеres.sendfile
Джо
Как вы решаете локальный путь?
4
path.resolveдолжен делать то, что вам нужно.
Джо
1
Это сделал это. Хотите обойти это как ответ?

Ответы:

286

Я верю, что это из-за относительного пути; «../» считается злонамеренным. Сначала разрешите локальный путь, затем позвоните res.sendfile. Вы можете решить путь с path.resolveзаранее.

var path = require('path');
res.sendFile(path.resolve('temp/index.html'));
Джо
источник
31
более подробная информация будет полезна для таких новичков, как я
Адам Уэйт
5
Экспресс считает относительные пути sendfileплохими. Если вы не укажете rootпараметр каталога, как показано здесь: github.com/visionmedia/express/issues/1465
Джо
2
var path = require ('path');
Мэтт Харрисон
1
да, последний код !!
SuperUberDuper
2
@MattHarrison ES6 обновление для пакетов импорта, constпредпочтительнееvar
Нино Filiu
39

Этот ответ собирает информацию из других ответов / комментариев.

Это зависит от того, хотите ли вы включить что-то относительно рабочего каталога процесса (cwd) или файлового каталога. Оба используют path.resolveфункцию (поставить var path = require('path')в верхней части файла.

  • относительно cwd: path.resolve('../../some/path/to/file.txt');
  • относительно файла: path.resolve(__dirname+'../../some/path/to/file.txt');

Прочитав ссылку из комментария @ Joe, вы узнаете, что относительные пути представляют угрозу безопасности, если вы принимаете ввод данных пользователем (например, это sendfile('../.ssh/id_rsa')может быть первая попытка хакера).

derekdreery
источник
1
Как новичок, я хочу знать, как хакерский сценарий пришел сюда?
Бхарат Муппа
2
Если вы случайно позволите пользователю ввести путь к файлу, который он хочет загрузить, он может загрузить любой файл в вашей системе (я привел пример закрытого ключа ssh - который даст им возможность притвориться вашим компьютером ( человек посередине и т. д.)). Наличие ограничения .. запрещает эту возможность, так как доступны только файлы с веб-сайта.
Дерекдрееры
30

Документация Express предлагает сделать это по-другому, и, на мой взгляд, это имеет смысл позже, чем текущее решение.

res.sendFile('index.html', {root: './temp'});

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

tenor528
источник
1
Это правда, но он использует sendFile (заглавная F, поддерживаемая Express v4.8.0 и далее) вместо более старого sendfile, который использовал OP. Просто говорю ... =]
RemyNL
Ааа ... хороший улов. Я не заметил этой маленькой разницы. Мне также интересно, если выбранный ответ работает не потому, что он использует, .sendfileа потому, что он полностью зависит от чего-то другого (путь). Спасибо за указание на это.
tenor528
Просто и эффективно. Спасибо! Это сработало для меня отлично!
Эмануэла