Вступление
В предыдущем посте мы рассмотрели, как создать REST API с использованием инфраструктуры Java Spring Boot и MongoDB. API, однако, не требовал никакой аутентификации, а это значит, что он, вероятно, все еще не готов к использованию. Поэтому в этом руководстве будет рассказано, как использовать встроенную среду безопасности Spring для добавления уровня аутентификации в этот API.
Почему нашему api нужна аутентификация?
API предоставляют простой интерфейс для взаимодействия с внутренними данными, поэтому имеет смысл, чтобы вы не хотели, чтобы кто попало имел доступ к этим данным и их изменению. Аутентификация гарантирует, что только заслуживающие доверия пользователи смогут получить доступ к API.
Почему мы должны хешировать пароли?
Мы все слышали о недавних кибератаках, в результате которых у крупных компаний были украдены пароли. Так почему же рекомендуется только менять наши пароли после взлома? Потому что эти крупные компании позаботились о том, чтобы пароли всегда хешировались в их базах данных!
Хотя все-равно всегда стоит менять пароли после подобных взломов данных, хеширование паролей чрезвычайно затрудняет поиск реального пароля пользователя, поскольку оно является односторонним алгоритмом. Фактически, могут потребоваться годы, чтобы взломать сложный пароль хешированный должным образом.
Authorization in mongodb (role-based access control)
In MongoDB, you control who has access to what resources on a database and to which degree through a mechanism called Role-Based Access Control, often shortened as RBAC.
Bcrypt для хеширования паролей
Хеширование — это односторонний алгоритм шифрования. По сути, после хеширования практически невозможно обнаружить, как выглядели исходные данные. Алгоритм хэширования BCrypt сначала солит фрагмент текста, а затем хеширует его до строки длиной 60 символов. Кодировщик Java BCrypt предлагает метод
matches
, который проверяет, соответствует ли строка хешу. Например, пароль
p@55w0Rd
, хешированный с помощью BCrypt, может иметь значение
$2b$10$Qrc6rGzIGaHpbgPM5kVXdeNZ9NiyRWC69Wk/17mttHKnDR2lW49KS
. При вызове метода
matches
BCrypt для незашифрованного и хешированного пароля мы получим значение
true
. Эти хеши могут быть сгенерированы с помощью встроенного в Spring Security кодировщика BCrypt.
Configure auth key
jsonwebtoken functions such as verify() or sign() use algorithm that needs a secret key (as String) to encode and decode token.
In the app/config folder, create auth.config.js file with following code:
module.exports = {
secret: "bezkoder-secret-key"
};
You can create your own secret String.
Configure mongodb database
In the app folder, create config folder for configuration.
Then create a new db.config.js file that contains parameters for setting up MongoDB later:
module.exports = {
HOST: "localhost",
PORT: 27017,
DB: "bezkoder_db"
};
Create node.js app
Create a folder for our project with command:
$ mkdir node-js-jwt-auth-mongodb
$ cd node-js-jwt-auth-mongodb
Then we initialize the Node.js App with a package.json file:
npm init
name: (node-js-jwt-auth-mongodb)
version: (1.0.0)
description: Node.js MongoDB: JWT Authentication & Authorization
entry point: (index.js) server.js
test command:
git repository:
keywords: node.js, express, jwt, authentication, mongodb
author: bezkoder
license: (ISC)
Is this ok? (yes) yes
Further reading
Fullstack:- MEVN: Vue.js Node.js Express MongoDB example- MEAN:
– MERN: React Node.js Express MongoDB example
Deployment: Docker Compose: Node.js Express and MongoDB example
How mongodb controls access with role-based access control
Access control — also known as authorization — is a security technique that involves determining who can gain access to which resources.
Node.js express architecture with authentication & authorization
Here is an overview of our Node.js Express App:
Prerequisites
To follow along with this guide, you’ll need an account on a MongoDB server with the appropriate privileges.
Project structure
This is directory structure for our Node.js Express & MongoDB application:
Required privileges
To execute the commands above, you need to login to MongoDB with an account with a number of different privilege actions. The specific privileges you require depend on the commands you need to use.
Setup express web server
In the root folder, let’s create a new server.js file:
Source code
You can find the complete source code for this tutorial on Github.
Using Cookies: Node.js Express and MongoDB: Login and Registration example
Step 1 — outlining the example scenario and preparing the sample databases
To explain how Role-Based Access Control — RBAC, for short — works in practice, this guide follows an example scenario with an imaginary sales company called Sammy Sales that uses two databases.
The first database (called sales) will store data about customer orders in the company shop with two separate collections: customers for their customers’ personal data and orders for order details.
The second database (this one called reports) will store aggregated reports on monthly sales. This database will contain a single collection named reports.
Technology
- Express 4.17.1
- bcryptjs 2.4.3
- jsonwebtoken 8.5.1
- mongoose 5.9.1
- MongoDB
Добавление зависимостей безопасности
В корневом каталоге проекта должен быть файл с именем
pom.xml
. Мы еще не трогали этот файл, но файл pom содержит все зависимости нашего проекта, и мы собираемся добавить туда парочку, поэтому давайте начнем с открытия этого файла и прокрутки вниз до тега
Единственная новая зависимость, в которой мы нуждаемся, — это spring-starter-security. Spring имеет встроенный менеджер версий, поэтому зависимость, которую мы должны добавить в тег <dependencies>, следующая:
И Maven загрузит исходные файлы за нас, так что наши зависимости должны быть готовыми к работе!
Добавление кодировщика bcrypt
Теперь нам нужно сказать Spring, чтобы он использовал кодировщик BCrypt для хеширования и сравнения паролей — это звучит как трудная задача, но на самом деле это очень просто. Мы можем добавить этот кодировщик, просто добавив следующие строки в наш класс
SecurityConfiguration
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
И все дела! Этот простой бин сообщает Spring, что PasswordEncoder, который мы хотим использовать, — это Spring Boot
BCryptPasswordEncoder()
для кодирования и сравнения хешей паролей. Spring Boot также включает несколько других кодировщиков паролей — рекомендую попробовать их, если вы хотите поэкспериментировать!
Добавление модели пользователей и репозитория
В предыдущем посте подробно рассказывалось о моделях и репозиториях Mongo, поэтому я не буду здесь вдаваться в подробности о том, как они работают — если вы хотите освежить знания, не стесняйтесь посетить мой предыдущий пост!
Добавление пользователя в mongodb
Я добавлю минимум полей, необходимых для моей коллекции
Как spring управляет безопасностью
Spring предлагает надстройку под названием
, которая делает аутентификацию легко настраиваемой и чрезвычайно простой. Мы даже можем использовать некоторые навыки, которые мы узнали в предыдущем посте, при настройке!
Как это работает
Мы будем использовать
Модель
Моделью будет базовый класс Java с пользовательскими
_id
Проверка аутентификации
Я протестирую быстрый
GET
-запрос с правильной и неправильной аутентификацией, чтобы убедиться, что конфигурация работает в соответствии с планом.
Неправильные Имя пользователя/Пароль
Репозиторий
Репозиторий будет называться
Создание конфигурации безопасности
src/main/resources/java/[package name]
с именем
config
, и мы также должны создать новый файл в этой папке конфигурации с именем
SecurityConfiguration.java
. Этот файл имеет несколько важных частей, поэтому давайте начнем с базового класса SecurityConfiguration:
Создание службы аутентификации
Нам нужно сообщить Spring, где находятся наши пользовательские данные и где найти информацию, необходимую для аутентификации. Для этого мы можем создать службу аутентификации (Authentication Service). Давайте начнем с создания новой папки в
src/main/resources/java/[package name]
под названием services, и мы можем создать новый файл в этой папке конфигурации с именем
Указание диспетчера аутентификации
Наконец, мы должны указать в нашей
SecurityConfiguration
, что мы хотим использовать
Этап аутентификации
Далее нам нужно сообщить Spring Security, как мы хотим обрабатывать аутентификацию пользователей. По умолчанию Spring Security имеет предопределенные имя пользователя и пароль,
. Однако мы хотим, чтобы наши пользователи использовали свое имя пользователя и пароль для доступа к базе данных. Кроме того, поскольку наши пользователи будут проходить повторную аутентификацию при каждом запросе, а не входить в систему, CSRF Protection и управление сеансами нам не нужны, поэтому мы можем добавить метод с именем
configure
, который переопределяет схему аутентификации по умолчанию, чтобы сообщить Spring, как именно мы хотим обрабатывать аутентификацию, и будет выглядеть следующим образом:
Initialize mongoose
Now create app/models/index.js with content like this:
Run & test with results
Run Node.js application with command: node server.js.
The console shows: