узел, экспресс - ограничить доступ к загружаемому файлу - PullRequest
0 голосов
/ 04 сентября 2018

Я использую express в качестве сервера для micro-services rest api. Конечные точки строятся из структуры каталогов. Есть несколько загружаемых файлов PDF, которые в настоящее время находятся на стороне клиента. И он может быть загружен (с URL href), даже если пользователь не вошел в портал. Итак, я положил все файлы PDF на сервер.

Структура каталогов на сервере: directory structure on server

pdf файлы находятся в директории docs. Пожалуйста, найдите ниже код сервера:

/* global __dirname */
import morgan from 'morgan';
import logger, { webStream } from './services/logger';
import { socket } from './services';

// set env variables before all else
import { GATEWAY_PORT, CORS_ORIGINS } from './config';

const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser')();
const version = require('./services/utils').version();
const authentication = require('./services/authentication');
const utils = require('./services/utils');


// set up app and middleware
const app = express();

app.use(morgan('User::req[user-id] Correlation::req[x-correlation-id] Method::method URL::url Status::status :res[content-length] - :response-time ms', { stream: webStream }));

logger.info('Starting...');

app.use(cookieParser);
app.use(bodyParser.json({ limit: '50mb' }));
app.disable('x-powered-by');

// CORS headers to allow running client/server on different ports
app.use((req, res, next) => {
  // Check if the origin is whitelisted in the env vars
  const actual = req.headers.origin || '';
  if (utils.matchCors(actual, CORS_ORIGINS.split(','))) {
    res.set({ 'Access-Control-Allow-Origin': actual });
  }

  res.set({
    // standard CORS headers
    'Access-Control-Allow-Headers': 'Content-Type, Authorization, Accept, Accept-Language',
    'Access-Control-Allow-Credentials': true,
    'Access-Control-Allow-Methods': 'PATCH,POST,GET,DELETE',

    // addresses security issues identified by automated pen testing
    'X-Frame-Options': 'DENY',
    'X-Content-Type-Options': 'nosniff',
    'X-XSS-Protection': 1,
  });
  next();
});

// set the user property of the request object
app.use((req, res, next) => {
  const token = req.cookies[authentication.cookieName];
  if (!token) {
    req.user = false;
  } else {
    req.user = authentication.decodeJWT(token);
    authentication.setCookie(res, token, req.user);
  }
  utils.setCorrelationId(req.headers['x-correlation-id']);
  req.correlationId = req.headers['x-correlation-id'];
  next();
});

// helper function returning middleware to reject unauthorised users
function requiredRoles(roles, abcOnly) {
  return function requireRolesHandler(req, res, next) {
    if (
      !req.user
      || (abcOnly && !req.user.isabc)
      || !authentication.hasRole(req.user, roles)) {
      const error = new Error('UNAUTHORISED');
      error.status = 403;
      next(error);
    } else {
      next();
    }
  };
}

// Add the endpoints to express.
// Reversed to get literal routes before @ capture groups.
utils.parseDirectory(`${__dirname}/rest`, [], true).reverse().forEach((endpoint) => {
  const { auth, functions } = endpoint.handler;
  if (auth) {
    functions.unshift(requiredRoles(auth.roles, auth.abcOnly));
  }
  app[endpoint.method](
    endpoint.url,
    functions,
  );
});


// setup server
const server = app.listen(GATEWAY_PORT, () => {
  logger.info(`Allowed CORS: ${CORS_ORIGINS}`);
  logger.info(`Started ${version.name} (${version.number}) listening on ${GATEWAY_PORT}`);
});

socket.createServer(server);

Как передать файлы pdf с сервера на клиент только авторизованному пользователю, когда пользователь нажимает на ссылку на странице?

1 Ответ

0 голосов
/ 04 сентября 2018

Есть маршрут для загрузки файла, например. GET /api/download?file=abc.pdf

Сейчас в промежуточном программном обеспечении,

  1. Проверьте, существует req.user или нет.

  2. Проверьте, обладает ли user достаточными правами для загрузки файла или не

  3. Если 1 и 2 удовлетворяют, то подать файл


Код будет выглядеть примерно так:

app.get('/api/download', (req, res, next) => {
  // Check if the request had valid token or not
  if(!req.user) {
    const error = new Error('UNAUTHORISED');
    error.status = 403;
    return next(error);
  }

  const { user } = req;
  const { file } = req.query;

  // If you want to have some additional logic wherein
  // you want to restrict the download of the file, 
  // you can put that logic in this function
  const isAllowed = canDownload(user, file);

  if(isAllowed) {
    return res.sendFile(path.join(__dirname, 'docs', path.sep, file));
  }
  const error = new Error('UNAUTHORISED');
  error.status = 403;
  return next(error);

})

Возможно, вам потребуется path, внедрить canDownload или устранить таких ошибок в файле или каталоге из-за использования __dirname. Все это тривиально. Если вам нужна помощь, дайте мне знать в комментариях.


Вот ссылка на response.sendFile ()
И это тоже может быть полезным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...