Express res.sendfile lançando erro proibido

160

Eu tenho este código:

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

No entanto, ele lança este erro:

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)

Alguém pode me dizer por que isso pode ser?


fonte
3
Eu acredito que é por causa do caminho relativo; o "../" é considerado malicioso. Resolver o caminho local em primeiro lugar, em seguida, chamarres.sendfile
Joe
Como você resolve o caminho local?
4
path.resolvedeve fazer o que você precisa.
Joe
1
Isso foi o que aconteceu. Quer deixar isso como resposta?

Respostas:

285

Eu acredito que é por causa do caminho relativo; o "../" é considerado malicioso. Resolva o caminho local primeiro e depois ligue res.sendfile. Você pode resolver o caminho com path.resolveantecedência.

var path = require('path');
res.sendFile(path.resolve('temp/index.html'));
Joe
fonte
31
mais detalhes seria útil aqui para iniciantes como eu
Adam Waite
5
O Express considera os caminhos relativos sendfileruins. A menos que você especificar o rootparâmetro de diretório, como visto aqui: github.com/visionmedia/express/issues/1465
Joe
2
var path = require ('caminho');
Matt Harrison
1
sim o código final !!
SuperUberDuper
2
Atualização @MattHarrison ES6, para as importações pacotes, consté preferido sobrevar
Nino Filiu
39

Esta resposta reúne as informações das outras respostas / comentários.

Depende se você deseja incluir algo relativo ao diretório ativo do processo (cwd) ou ao diretório do arquivo. Ambos usam a path.resolvefunção (coloque var path = require('path')na parte superior do arquivo.

  • em relação ao cwd: path.resolve('../../some/path/to/file.txt');
  • em relação ao arquivo: path.resolve(__dirname+'../../some/path/to/file.txt');

Ao ler o link do comentário de @ Joe, parece que os caminhos relativos são um risco de segurança se você aceitar a entrada do usuário para o caminho (por exemplo, sendfile('../.ssh/id_rsa')pode ser a primeira tentativa de um hacker).

derekdreery
fonte
1
Como um novato, quero saber como o cenário hacker chegou aqui?
bharath muppa
2
Se você acidentalmente permitir que o usuário insira o caminho do arquivo que deseja baixar, ele poderá fazer o download de qualquer arquivo em seu sistema (dei o exemplo de uma chave privada ssh - que permitiria fingir ser seu PC ( homem do meio, etc)). Tendo a restrição .. não permite essa possibilidade, pois apenas os arquivos do site podem ser acessados.
derekdreery
30

A documentação do Express sugere fazê-lo de uma maneira diferente e, na minha opinião, faz mais sentido depois da solução atual.

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

A opção raiz parece definir ./como o diretório raiz do seu projeto. Portanto, não sei exatamente onde está o seu arquivo em relação à raiz do projeto, mas se a sua pasta temporária estiver lá, você poderá definir ./tempcomo a raiz do arquivo que está enviando.

tenor528
fonte
1
Isso é verdade, mas usa sendFile (capital F, suportado pelo Express v4.8.0 em diante) em vez do arquivo de envio mais antigo que o OP estava usando. Apenas dizendo ... =]
RemyNL 10/02
Ahh ... boa captura. Não notei essa pequena diferença. Também me pergunto se a resposta selecionada funciona não porque usa, .sendfilemas porque depende de outra coisa completamente (caminho). Obrigado por apontar isso.
tenor528
Simples e eficiente. Obrigado! Isso funcionou para mim perfeitamente!
Emanuela Colta