Тъй като популярността на Node.js продължава да нараства, става все по-важно да се защитят API, изградени с помощта на тази платформа. Два ефективни начина да направите това са чрез използването на JSON уеб токени (JWT) за удостоверяване и ограничаване на скоростта за предотвратяване на груби атаки и други злонамерени действия.

В тази статия ще ви покажем как да защитите вашия Node.js API с JWT базирано удостоверяване и ограничаване на скоростта. Като приложите тези две техники заедно, можете значително да подобрите сигурността на вашия API и да защитите данните на вашите потребители.

Какво представляват JSON уеб токените?

JSON уеб токените са стандарт за сигурно представяне на искове между две страни. JWT се състоят от три части: заглавка, полезен товар и подпис. Заглавието и полезният товар са JSON низове, кодирани с Base64Url, докато подписът се използва за проверка на целостта на токена.

JWT обикновено се използват за удостоверяване в уеб приложения. След като потребителят влезе, JWT му се издава и се изпраща обратно на клиента. След това клиентът включва този токен в следващите заявки към сървъра. След това сървърът може да декодира токена и да провери неговия подпис, за да се увери, че не е бил подправен. Ако токенът е валиден, сървърът може да извлече информация от полезния товар, за да идентифицира потребителя и да разреши неговата заявка.

Как да внедрим JWT-базирано удостоверяване в Node.js

За да приложите базирано на JWT удостоверяване в Node.js, ще трябва да инсталирате библиотеката jsonwebtoken. Тази библиотека предоставя функции за генериране и проверка на JWT. Ето пример за това как да генерирате JWT:

const jwt = require('jsonwebtoken');

const payload = {
  user: 'johndoe'
};

const secret = 'mysecret';

const token = jwt.sign(payload, secret, { expiresIn: '1h' });

console.log(token);

В този пример ние генерираме JWT с полезен товар, съдържащ свойство user, зададено на johndoe. Използваме таен ключ mysecret, за да подпишем токена, и задаваме време за изтичане от 1 час, като използваме опцията expiresIn.

За да проверите JWT, можете да използвате функцията verify на библиотеката jsonwebtoken:

const jwt = require('jsonwebtoken');

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiam9obmRvZSJ9.-MQPfE60laMNGxyZsUbIb3AsA0y0FVmqr2k7_UimN_g';

const secret = 'mysecret';

jwt.verify(token, secret, (err, decoded) => {
  if (err) {
    console.error(err);
  } else {
    console.log(decoded);
  }
});

В този пример ние проверяваме JWT с функцията verify. Предаваме JWT и секретния ключ, използван за подписване на токена. Ако токенът е валиден, декодираният полезен товар ще бъде регистриран в конзолата.

Какво е ограничаване на скоростта?

Ограничаването на скоростта е техника, използвана за предотвратяване на злоупотреба с API чрез ограничаване на броя заявки, които могат да бъдат направени в рамките на даден период от време. Това може да помогне за предотвратяване на груби атаки, DDoS атаки и други форми на злонамерена дейност.

Има много стратегии за ограничаване на скоростта, но един общ подход е да се ограничи броят на заявките за IP адрес за период от време. Например, можете да ограничите всеки IP адрес до 100 заявки на час.

Как да внедрите ограничаване на скоростта в Node.js

За да приложите ограничаване на скоростта във вашето приложение NodeJS, можете да използвате пакет като „express-rate-limit“. Този пакет предоставя междинен софтуер, който може да се използва за ограничаване на броя на заявките от определен IP адрес в рамките на определен период от време. Ето един пример:

const rateLimit = require("express-rate-limit");

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs
});

// apply to all requests
app.use(limiter);

В горния код създаваме ограничител на скоростта, който позволява максимум 100 заявки на IP адрес в рамките на 15-минутен прозорец. След това този междинен софтуер се прилага към всички заявки, използващи app.use(limiter).

Сега нека интегрираме този ограничител на скоростта с нашата JWT система за удостоверяване. Ще модифицираме нашия jwtVerify междинен софтуер, за да проверим и лимита на скоростта за входящата заявка:

const jwt = require("jsonwebtoken");
const rateLimit = require("express-rate-limit");

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs
});

function jwtVerify(req, res, next) {
  // Check if the request has a JWT token in the Authorization header
  const token = req.headers.authorization;

  if (!token) {
    return res.status(401).json({ message: "Authorization header not found" });
  }

  // Verify the JWT token and extract the payload
  jwt.verify(token, secretKey, (err, payload) => {
    if (err) {
      return res.status(401).json({ message: "Invalid token" });
    }

    // Check the rate limit for the incoming request
    const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
    limiter.get(ip, (err, limit) => {
      if (err) {
        return next(err);
      }

      // Check if the request has exceeded the rate limit
      if (limit.remaining === 0) {
        return res.status(429).json({ message: "Too many requests" });
      }

      // Update the rate limit for the incoming request
      res.set("X-RateLimit-Limit", limit.total);
      res.set("X-RateLimit-Remaining", limit.remaining - 1);

      // Save the JWT payload in the request object for future use
      req.user = payload;

      // Call the next middleware in the chain
      next();
    });
  });
}

// Apply the rate limiter and JWT middleware to all API endpoints
app.use(limiter);
app.use("/api", jwtVerify);

В горния код сме модифицирали нашия jwtVerify междинен софтуер, за да проверим и лимита на скоростта за входящата заявка, използвайки метода limiter.get(). Ако заявката е надхвърлила ограничението за скорост, ние връщаме отговор 429 със съобщението „Твърде много заявки“. В противен случай актуализираме заглавките на ограничението на скоростта в отговора и запазваме JWT полезния товар в обекта на заявката за бъдеща употреба.

И накрая, прилагаме както ограничителя на скоростта, така и JWT междинния софтуер към всички крайни точки на API, използвайки app.use(). Сега нашият NodeJS API е защитен както с JWT удостоверяване, така и с ограничаване на скоростта, за да се предотврати злоупотреба и да се гарантира неговата наличност за законни потребители.