Рубрики
Без рубрики

Защита Node.js RESTFLE APIS с JSON WEB TOKENS

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

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

Это будет пошаговое учебное поставление о том, как добавить аутентификацию на основе токена на существующую API для отдыха. Обеспечение стратегии аутентификации – JWT (Web Token Json). Если это не скажет вам много, это нормально. Это было так же странно для меня, когда я впервые услышал термин.

Что значит JWT на точке зрения на землю на землю? Давайте сломаемся, как говорится о официальном определении:

Это было глоток. Давайте переведем это на английский. JWT – это кодированная строка символов, которая безопасна для отправки между двумя компьютерами, если у них обоих есть https. Токен представляет собой значение, которое доступно только компьютером, который имеет доступ к секретному ключу, с помощью которого он был зашифрован. Достаточно просто, верно?

Как это выглядит в реальной жизни? Допустим, пользователь хочет войти в свой аккаунт. Они отправляют запрос с требуемыми учетными данными, такими как адрес электронной почты и пароль к серверу. Сервер проверяет, верны ли учетные данные. Если они есть, сервер создает токен, используя желаемую полезную нагрузку и секретный ключ. Эта строка символов, которые результаты из шифрования называются токеном. Затем сервер отправляет его обратно клиенту. Клиент, в свою очередь, сохраняет токен, чтобы использовать его во всех других запросах, который пользователь отправит. Практика добавления токена к заголовкам запроса – это как способ авторизовать пользователю доступа к ресурсам. Это практический пример того, как работает JWT.

Хорошо, это достаточно разговоров! Остальная часть этого учебника будет кодироваться, и я бы понравилось, если бы вы следили за мной и кодом рядом со мной, как мы прогрессируем. Каждый фрагмент кода будет сопровождаться объяснением. Я верю, что лучший способ понять это правильно, будет кодировать его самостоятельно.

Прежде чем начать, есть некоторые вещи, которые вам нужно знать о Node.js, и некоторые стандарты Ecmascript, я буду использовать. Я не буду использовать ES6, так как он не такой же, как для начинающих, как традиционный JavaScript. Но я ожидаю, что вы уже знаете, как построить спокойную API с Node.js. Если нет, вы можете взять объезд и Проверьте это прежде чем продолжить.

Кроме того, Целая демонстрация на Github Если вы хотите увидеть это полностью.

Давайте начнем писать какой-нибудь код, будем ли мы?

Ну, еще не на самом деле. Нам нужно сначала настроить окружающую среду. Код придется подождать хотя бы пару больше минут. Эта часть скучная так, чтобы встать и быстро работать, мы будем клонировать репозиторий из учебника выше. Откройте окно терминала или командную строку Подскажите и запустите эту команду:

git clone https://github.com/adnanrahic/nodejs-restful-api.git

Вы увидите появившуюся папку, откройте ее. Давайте посмотрим на структуру папки.

> user
  - User.js
  - UserController.js
- db.js
- server.js
- app.js
- package.json

У нас есть папка пользователя с моделью и контроллером, а базовый CRUD уже реализован. Наше app.js Содержит базовую конфигурацию. db.js Убедитесь, что приложение подключается к базе данных. Server.js Убедитесь, что наш сервер вращается.

Продолжайте и установите все необходимые узловые модули. Переключитесь обратно в ваше окно терминала. Убедитесь, что вы в папке по имени Nodejs-Restful-API и бежать Установка NPM . Подождите секунду или два для модулей для установки. Теперь вам нужно добавить строку подключения к базе данных в db.js Отказ

Перейти к MLAB Создайте учетную запись, если у вас еще нет одного, и откройте панель Dashboard с базой данных. Создайте новую базу данных, назовите ее по желанию и перейдите к своей странице конфигурации. Добавьте пользователя базы данных в вашу базу данных и скопируйте строку подключения с помощью приборной панели в свой код.

Все, что вам нужно сделать сейчас, это изменить ценности заполнителя для и Отказ Замените их имя пользователя и пароль пользователя, созданного для базы данных. Подробный шаг за шагом объяснение этого процесса можно найти в Учебник, связанный выше Отказ

Допустим, пользователь, который я создал для базы данных, называется Уолли с паролем TheFlashisawesome Отказ Имея это в виду, db.js Файл должен выглядеть что-то подобное:

var mongoose = require('mongoose');
mongoose.connect('mongodb://wally:theflashisawesome@ds147072.mlab.com:47072/securing-rest-apis-with-jwt', { useMongoClient: true });

Продолжай и раскрутите сервер, обратно в свой тип окна терминала Node Server.js Отказ Вы должны увидеть Экспресс-сервер, слушающий на порт 3000 Войдите в систему в терминал.

Наконец, какой-то код.

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

Во-вторых, мы хотим добавить авторизацию. Акт предоставления пользователей разрешения на доступ к определенным ресурсам на нашем API для отдыха.

Начните, добавив новый файл в корневом каталоге проекта. Дайте ему имя config.js Отказ Здесь вы поставите настройки конфигурации для приложения. Все, что нам нужно в данный момент, просто определить секретный ключ для нашей сети JSON Токен.

Отказ от ответственности : Имейте в виду, ни при каких обстоятельствах вы не должны когда-либо, (всегда!) У вашего секретного ключа публично видна так. Всегда кладите все свои ключи в переменные окружающей среды! Я только пишу это только для демонстрации демонстрации.

// config.js
module.exports = {
  'secret': 'supersecret'
};

С этим добавлено, вы готовы начать добавлять логику аутентификации. Создать папку с именем auth и начните, добавив файл с именем Authcontroller.js Отказ Этот контроллер будет домом для нашей логики аутентификации.

Добавьте этот кусок кода на вершину Authcontroller.js Отказ

// AuthController.js

var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());
var User = require('../user/User');

Теперь вы готовы добавить модули для использования JSON WEB TOKENS. и Шифрование паролей Отказ Вставьте этот код в Authcontroller.js :

var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
var config = require('../config');

Откройте окно терминала в папке проекта и установите следующие модули:

npm install jsonwebtoken --save
npm install bcryptjs --save

Это все модули, которые нам нужно для реализации нашей желаемой аутентификации. Теперь вы готовы создать /Регистрация конечная точка. Добавьте этот кусок кода на ваш Authcontroller.js :

router.post('/register', function(req, res) {
  
  var hashedPassword = bcrypt.hashSync(req.body.password, 8);
  
  User.create({
    name : req.body.name,
    email : req.body.email,
    password : hashedPassword
  },
  function (err, user) {
    if (err) return res.status(500).send("There was a problem registering the user.")
    // create a token
    var token = jwt.sign({ id: user._id }, config.secret, {
      expiresIn: 86400 // expires in 24 hours
    });
    res.status(200).send({ auth: true, token: token });
  }); 
});

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

jwt.sign () Метод принимает полезную нагрузку и секретный ключ, определенный в config.js в качестве параметров. Это создает уникальную строку символов, представляющих полезную нагрузку. В нашем случае полезная нагрузка является объектом, содержащим только идентификатор пользователя. Давайте напишем кусок кода, чтобы получить идентификатор пользователя на основе токена, который мы вернулись с конечной точки регистра.

router.get('/me', function(req, res) {
  var token = req.headers['x-access-token'];
  if (!token) return res.status(401).send({ auth: false, message: 'No token provided.' });
  
  jwt.verify(token, config.secret, function(err, decoded) {
    if (err) return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });
    
    res.status(200).send(decoded);
  });
});

Здесь мы ожидаем, что токен будет отправлен вместе с запросом в заголовках. Имя по умолчанию для токена в заголовках HTTP-запроса – X-Access-токен Отказ Если нет токена, предоставленного с запросом, сервер отправляет ошибку. Быть более точным, 401 Несанкционировано Статус с ответным сообщением Нет токена не предоставлено Отказ Если токен существует, jwt.veryify () Метод будет вызван. Этот метод декодирует токен, позволяющий просматривать оригинальную полезную нагрузку. Мы рассмотрим ошибки, если есть какие-либо и если нет, отправьте обратно декодированное значение как ответ.

Наконец, нам нужно добавить маршрут к Authcontroller.js В нашем главном app.js файл. Первый экспорт маршрутизатора от Authcontroller.js :

// add this to the bottom of AuthController.js
module.exports = router;

Затем добавьте ссылку на контроллер в основном приложении, прямо здесь, где вы экспортировали приложение.

// app.js
var AuthController = require('./auth/AuthController');
app.use('/api/auth', AuthController);
module.exports = app;

Давайте проверим это. Почему нет?

Откройте ваш инструмент тестирования API для отдыха API, я использую Почтальон или Бессонница , но любой сделает.

Вернитесь к вашему терминалу и запустите Node Server.js Отказ Если он работает, остановите его, сохраните все изменения в файлы, и запустите Node Server.js опять таки.

Откройте почтальон и нажмите в конечную точку регистра ( /API/Auth/Register ). Обязательно подобрать метод Post и X-www-form-url-кодированный Отказ Теперь добавьте некоторые значения. Имя моего пользователя – Mike, и его пароль – «ThisisSecretPassword». Это не лучший пароль, который я когда-либо видел, если честно, но это будет делать. Хит отправить!

Смотрите ответ? Токен – это длинная срубленная нить. Попробовать /API/AUTH/ME Конечная точка, сначала скопируйте токен. Измените URL на /меня вместо того /Регистрация и метод получить. Теперь вы можете добавить токен на заголовок запроса.

Вуаля! Токен был декодирован в объекте с идентификационным полем. Хотите убедиться, что идентификатор действительно принадлежит Mike, пользователь, который мы только что создали? Уверен, что вы делаете. Перепрыгись назад в свой редактор кода.

// in AuthController.js change this line
res.status(200).send(decoded);

// to
User.findById(decoded.id, function (err, user) {
  if (err) return res.status(500).send("There was a problem finding the user.");
  if (!user) return res.status(404).send("No user found.");
  
  res.status(200).send(user);
});

Теперь, когда вы отправляете запрос на /меня Конечная точка вы увидите:

Ответ теперь содержит весь объект пользователя! Прохладный! Но, не хорошо. Пароль никогда не должен быть возвращен с другими данными о пользователе. Давайте исправим это. Мы можем добавить проекцию в запрос и опустить пароль. Нравится:

User.findById(decoded.id, 
  { password: 0 }, // projection
  function (err, user) {
    if (err) return res.status(500).send("There was a problem finding the user.");
    if (!user) return res.status(404).send("No user found.");
    
    res.status(200).send(user);
});

Это лучше, теперь мы можем увидеть все значения, кроме пароля. Майк выглядит хорошо.

Кто-то сказал логин?

После внедрения регистрации мы должны создать способ для существующих пользователей войти в систему. Давайте подумаем об этом на секунду. Конечная точка регистрации требовала нас создать пользователь, хеш-пароль и выдавать токен. Какая конечная точка входа будет нам реализовать? Он должен проверить, существует ли пользователь с данным письмом вообще. Но также проверьте, соответствует ли предоставленное пароль Haved Password в базе данных. Только тогда мы хотим выдать токен. Добавьте это на ваш Authcontroller.js Отказ

router.post('/login', function(req, res) {

  User.findOne({ email: req.body.email }, function (err, user) {
    if (err) return res.status(500).send('Error on the server.');
    if (!user) return res.status(404).send('No user found.');
    
    var passwordIsValid = bcrypt.compareSync(req.body.password, user.password);
    if (!passwordIsValid) return res.status(401).send({ auth: false, token: null });
    
    var token = jwt.sign({ id: user._id }, config.secret, {
      expiresIn: 86400 // expires in 24 hours
    });
    
    res.status(200).send({ auth: true, token: token });
  });
  
});

Прежде всего, мы проверяем, существует ли пользователь. Затем используя Bcrypt’s .comparesync. () Метод сравниваем пароль, отправленный с запросом паролем в базе данных. Если они соответствуют нам .sign () токен. Это в значительной степени это. Давайте попробуем это.

Круто работает! Что делать, если мы ошибся паролем?

Отлично, когда пароль неверный, сервер отправляет статус ответа 401 Несанкционировано Отказ Только то, что мы хотели!

Чтобы завершить эту часть учебника, давайте добавим простую конечную точку выхода в систему, чтобы аннулировать токен.

// AuthController.js
router.get('/logout', function(req, res) {
  res.status(200).send({ auth: false, token: null });
});

Отказ от ответственности : Конечная точка выхода не требуется. Акт регистрации может быть выполнен исключительно через клиентскую сторону. Токен обычно хранится в файле cookie или Localstorage браузера. Регистрация – так же просто, как уничтожать токен на клиенте. Это /Выход из системы Конечная точка создана для логически изображенного, что происходит, когда вы выходите. Токен устанавливается на null Отказ

С этим мы закончили Аутентификация Часть учебника. Хотите перейти к авторизации? Бьюсь об заклад, вы.

У вас есть разрешение быть здесь?

Чтобы понять логику за стратегией авторизации, нам нужно обернуть голову вокруг чего-то называемого промежуточное программное обеспечение Отказ Его зовут самоуверенно, в некоторой степени не так ли? Промежуточное ПО – это кусок кода, функция в Node.js, которая действует как мост между некоторыми частями вашего кода.

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

router.get('/me', function(req, res, next) {
    
  var token = req.headers['x-access-token'];
  if (!token) return res.status(401).send({ auth: false, message: 'No token provided.' });
  
  jwt.verify(token, config.secret, function(err, decoded) {
    if (err) return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });
    
    User.findById(decoded.id, 
    { password: 0 }, // projection
    function (err, user) {
      if (err) return res.status(500).send("There was a problem finding the user.");
      if (!user) return res.status(404).send("No user found.");
        
      // res.status(200).send(user); Comment this out!
      next(user); // add this line
    });
  });
});

// add the middleware function
router.use(function (user, req, res, next) {
  res.status(200).send(user);
});

Перепрыгивайте до почтальона и проверьте, что происходит, когда вы попадаете в /API/AUTH/ME конечная точка. Вы удивляете вас, что результат точно такой же? Должен быть!

Отказ от ответственности : Продолжайте и удалите этот образец, прежде чем продолжить, так как он используется только для демонстрации логики использования Далее () Отказ

Давайте возьмем эту же логику и применим его, чтобы создать функцию промежуточного программного обеспечения для проверки достоверности токенов. Создайте новый файл в auth папка и назвать ее VerifyToken.js Отказ Вставьте этот фрагмент кода там.

var jwt = require('jsonwebtoken');
var config = require('../config');

function verifyToken(req, res, next) {
  var token = req.headers['x-access-token'];
  if (!token)
    return res.status(403).send({ auth: false, message: 'No token provided.' });
    
  jwt.verify(token, config.secret, function(err, decoded) {
    if (err)
    return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });
      
    // if everything good, save to request for use in other routes
    req.userId = decoded.id;
    next();
  });
}

module.exports = verifyToken;

Давайте сломаемся. Мы собираемся использовать эту функцию в качестве пользовательского промежуточного программного обеспечения, чтобы проверить, существует ли токен и действительно ли это. После его подтверждения мы добавляем декодировать .id Соотношение к запросу ( req ) переменная. Теперь у нас есть доступ к нему в следующей функции в строке в цикле запроса-ответа. Призыв Далее () Убедитесь, что поток будет продолжаться к следующей функции ожидания в строке. В конце концов, мы экспортируем функцию.

Теперь открыть Authcontroller.js снова. Добавить ссылку на VerifyToken.js В верхней части файла и редактируйте конечная точка. Теперь он должен выглядеть так:

// AuthController.js

var VerifyToken = require('./VerifyToken');

// ...

router.get('/me', VerifyToken, function(req, res, next) {

  User.findById(req.userId, { password: 0 }, function (err, user) {
    if (err) return res.status(500).send("There was a problem finding the user.");
    if (!user) return res.status(404).send("No user found.");
    
    res.status(200).send(user);
  });
  
});

// ...

Посмотрите, как мы добавили VerifyToken В цепочке функций? Теперь мы обрабатываем все авторизацию в промежуточном программе. Это освобождает все пространство в обратном вызове, чтобы обработать только логику, нам нужно. Это удивительный пример того, как написать сухой код. Теперь каждый раз, когда вам нужно разрешить пользователю, вы можете добавить эту промежуточную программу на цепочку. Опять тестируйте его в почтальон, чтобы убедиться, что он все еще работает, как следует.

Не стесняйтесь связываться с токеном и попробуйте конечную точку снова. С неверным токеном вы увидите желаемое сообщение об ошибке, и убедитесь, что код, который вы написали, работает так, как вы хотите.

Почему это так мощно? Теперь вы можете добавить VerifyToken промежуточное программное обеспечение на любую цепочку функций и убедиться, что конечные точки защищены. Только пользователи с проверенными токенами могут получить доступ к ресурсам!

Удавая голову во всем.

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

Опять же, Вот репозиторий GitHub Отказ Вы можете догнать любые вещи, которые вы, возможно, пропустили, или просто посмотрите на код, если вы застряли.

Помните, аутентификация Является ли акт регистрации пользователя в. Авторизация Является ли акт проверки прав доступа пользователя взаимодействовать с ресурсом.

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

Надеюсь, вы, ребята, и девочки наслаждались, читая это так сильно, как мне нравилось писать. До следующего раза, будь любопытно и повеселиться.

Как вы думаете, что это учебное пособие будет поможет кому-то? Не стесняйтесь делиться. Если вам понравилось, пожалуйста, хлопайте для меня.

Оригинал: “https://www.freecodecamp.org/news/securing-node-js-restful-apis-with-json-web-tokens-9f811a92bb52/”