Triển khai xác thực người dùng trong ứng dụng Express
Xác thực người dùng là quá trình xác minh danh tính của người dùng đang cố gắng giành quyền truy cập vào ứng dụng của bạn. Nó liên quan đến việc ủy quyền và chuyển thông tin đăng nhập để xác nhận tính xác thực của người dùng.
Bạn có thể triển khai một mô hình xác thực người dùng đơn giản trong Node.js bằng cách sử dụng Express, Bcrypt và MongoDB, chỉ trong một vài bước.
Mục Lục
Bước 1: Thiết lập môi trường phát triển
Đầu tiên, tạo một thư mục dự án và đĩa CD vào nó bằng cách chạy:
mkdir user-authentication
cd user-authentication
Tiếp theo, khởi tạo npm trong thư mục dự án của bạn bằng cách chạy:
npm init -y
Các -y cờ khởi tạo npm và tạo package.json tệp với tất cả các giá trị mặc định của nó.
Mô hình xác thực người dùng này yêu cầu một số phụ thuộc.
Chúng bao gồm:
- Express: Express là một khung công tác Node.js cung cấp một tập hợp các tính năng mạnh mẽ cho các ứng dụng web và di động. Nó giúp việc xây dựng các ứng dụng phụ trợ với Node.js trở nên dễ dàng hơn.
- Bcrypt: bcrypt là một gói npm triển khai chức năng băm mật khẩu bcrypt. Nó cho phép bạn tạo hàm băm từ các chuỗi mật khẩu thuần túy.
- Mongoose: Mongoose là một thư viện mô hình dữ liệu đối tượng MongoDB. Nó đơn giản hóa các tương tác giữa ứng dụng của bạn và cơ sở dữ liệu MongoDB.
- dotenv: dotenv là một gói không phụ thuộc, tải các biến môi trường từ một .env nộp vào process.env.
- Validator: validator là một gói chứa các hàm xác thực chuỗi khác nhau.
- Body-parser: Gói body-parser phân tích cú pháp các phần thân yêu cầu trong phần mềm trung gian trước các trình xử lý của bạn.
Cài đặt các gói bằng cách chạy:
npm install express bcrypt mongoose dotenv validator body-parser
Tiếp theo, tạo một app.js tệp trong thư mục gốc của dự án của bạn và thêm khối mã bên dưới để tạo một máy chủ Express cơ bản:
const express = require('express');
const app = express();
const bodyParser = require("body-parser");const port = 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(port, ()=>{
console.log(`App is listening on port ${port}`);
});
Mã này tạo ra một phiên bản ứng dụng nhanh bằng cách gọi hàm express. Sau đó, nó sử dụng phân tích cú pháp cơ thể phần mềm trung gian để phân tích cú pháp các phần thân yêu cầu đến. Sau đó, nó bắt đầu lắng nghe lưu lượng truy cập trên cổng 3000 bằng cách gọi phương thức lắng nghe của cá thể express và chuyển biến cổng làm đối số.
Bước 2: Kết nối ứng dụng của bạn với cơ sở dữ liệu
Trong thư mục gốc của dự án của bạn, hãy tạo một .env tệp và lưu trữ thông tin đăng nhập MongoDB của bạn trong đó. Điều này tránh để lộ thông tin đăng nhập cơ sở dữ liệu của bạn trong mã có thể cung cấp cho người dùng độc hại quyền truy cập vào cơ sở dữ liệu của bạn.
Tiếp theo, điều hướng đến app.js tệp và nhập mongoose:
const mongoose = require("mongoose");
Sau đó, gọi nhập dotenv và gọi cho cấu hình phương pháp trên đó:
require("dotenv").config();
Gọi cho cấu hình phương pháp trên dotenv tải các biến môi trường vào process.env.
Cuối cùng, gọi phương thức kết nối trên cầy mangut và chuyển URI MongoDB của bạn làm đối số:
mongoose.connect(process.env.MONGODB_URI).then(() => {
console.log('Connected to Database Successfully')
})
Bước 3: Tạo mô hình người dùng
Trong thư mục gốc của dự án của bạn, hãy tạo một “người mẫu” thư mục; đây là nơi bạn sẽ lưu trữ mô hình cầy mangut của mình:
mkdir models
Tiếp theo, tạo một “userModel”Và thêm các lần nhập sau:
const mongoose = require('mongoose')
const { isEmail } = require('validator')
isEmail là một hàm xác thực trả về thật nếu một chuỗi nhất định là một email. Bạn sẽ cần nó để áp dụng xác thực mongoose cho mô hình người dùng của mình.
Tiếp theo, thêm mã sau vào userModel tập tin:
const userSchema = mongoose.Schema({
email: {
type: String,
required: [true, 'Email is required'],
validate: {
validator: isEmail,
message: props => `${props.value} is not a valid email`
}
},password: {
type: String,
required: [true, 'Password is required'],
validate: {
validator: function (value) {
return value.length >= 6
},
message: () => 'Password must be at least six characters long'
}
}
})
module.exports = mongoose.model('User', userSchema)
Đoạn mã trên tạo ra một userSchema biến lưu trữ giá trị của cầy mangut.Schema phương pháp. Phương thức mongoose.Schema ánh xạ các thuộc tính vào bộ sưu tập MongoDB và xác định hình dạng của các tài liệu bên trong nó. Lược đồ mongoose có hai thuộc tính — một e-mail và một mật khẩu mở khóa—Đó sẽ là các yêu cầu xác thực của bạn.
Thuộc tính email là một loại chuỗi và có yêu cầu đặt thành true. Thông báo lỗi kèm theo, “Email là bắt buộc”, sẽ hiển thị nếu nội dung yêu cầu không chứa e-mail tài sản. Cuối cùng, bằng cách sử dụng xác thực tùy chỉnh mongoose, người xác nhận tài sản giới thiệu isEmail hàm số. Hàm đó trả về true hoặc false dựa trên tính hợp lệ của chuỗi dưới dạng email. Sau đó, thuộc tính message nhận giá trị email (đạo cụ) và xây dựng một thông báo lỗi có ý nghĩa.
Thuộc tính mật khẩu là một loại chuỗi bắt buộc với thông báo lỗi có nội dung “Mật khẩu là bắt buộc”. Các người xác nhận là một hàm ẩn danh trả về true nếu mật khẩu dài ít nhất sáu ký tự.
Dòng cuối cùng tạo và xuất mô hình mongoose bằng cách gọi người mẫu phương pháp trên cầy mangut. Chuyển tên mô hình (Người sử dụng) dưới dạng đối số đầu tiên và một lược đồ (userSchema) như là đối số thứ hai.
Bước 4: Triển khai các tuyến đường đăng nhập và đăng ký
Trong thư mục gốc của dự án của bạn, hãy tạo một các tuyến đường thư mục:
mkdir routes
Trong thư mục tuyến đường của bạn, hãy tạo một userRoutes.js tập tin và thêm các lần nhập sau:
const express = require("express");
const User = require("../models/userModel");
const bcrypt = require("bcrypt");
Tạo một phiên bản Bộ định tuyến nhanh bằng cách gọi Bộ định tuyến phương pháp trên bày tỏ:
const router = express.Router();
Tiếp theo, tạo lộ trình đăng ký của bạn bằng cách thêm khối mã bên dưới vào userRoute.js tập tin:
router.post("/sign-up", async (req, res) => {
try {
const { email, password } = req.body;// Check if the email is already in use
let userExists = await User.findOne({ email });
if (userExists) {
res.status(401).json({ message: "Email is already in use." });
return;
}
const saltRounds = 10;
bcrypt.hash(password, saltRounds, (err, hash) => {
if (err) throw new Error("Internal Server Error");
// Create a new user
let user = new User({
email,
password: hash,
});
user.save().then(() => {
res.json({ message: "User created successfully", user });
});
});
} catch (err) {
return res.status(401).send(err.message);
}
});
Trong khối mã ở trên, trước tiên, bạn hủy cấu trúc email và mật khẩu khỏi req.body sự vật. Sau đó, hãy kiểm tra xem người dùng đã sử dụng email chưa vì email này phải là duy nhất cho mỗi người dùng. Nếu email đã được sử dụng, bạn quay lại và dừng thực thi mã với mã trạng thái 401.
Lưu trữ mật khẩu thuần túy trong cơ sở dữ liệu là một mối đe dọa bảo mật lớn vì các tin tặc độc hại có thể truy cập vào cơ sở dữ liệu. Bạn nên băm mật khẩu trước khi đưa chúng vào cơ sở dữ liệu của mình, vì vậy, ngay cả khi một hacker phát hiện ra chúng, sẽ không gây rủi ro cho người dùng. Hashing là quá trình chuyển đổi một “khóa” đã cho thành một giá trị khác. Hashing là một hàm một chiều, có nghĩa là bạn không thể lấy giá trị ban đầu từ giá trị đã được băm, không giống như mã hóa.
Sử dụng bcrypt, bạn đã băm mật khẩu người dùng của mình bằng cách gọi phương thức băm trên bcrypt. Phương thức băm nhận ba tham số: chuỗi được băm, vòng muối và hàm gọi lại. Bạn chuyển mật khẩu người dùng, biến SaltRounds mà bạn đã tạo trước đó và một lệnh gọi lại.
Vòng muối đề cập đến thời gian cần thiết để tính toán một hàm băm bcrypt. Vòng muối càng cao thì số vòng băm càng nhiều.
Nếu phương thức băm gây ra lỗi, bạn sẽ gặp phải “lỗi máy chủ nội bộ”. Nếu không, bạn đặt thuộc tính mật khẩu thành hàm băm thành công và lưu nó vào cơ sở dữ liệu của bạn bằng cách gọi phương thức lưu trên Người sử dụng ví dụ.
Tiếp theo, tạo lộ trình đăng nhập của bạn bằng cách thêm khối mã bên dưới vào userRoute.js tập tin:
router.post("/sign-in", async (req, res) => {
try {
const { email, password } = req.body;// Check if user exists in database
let user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ message: "Invalid Credentials" });
}
bcrypt.compare(password, user.password, (err, result) => {
if (result) {
return res.status(200).json({ message: "User Logged in Successfully" });
}
console.log(err);
return res.status(401).json({ message: "Invalid Credentials" });
});
} catch (error) {
res.status(401).send(err.message);
}
});
module.exports = router;
Trong khối mã ở trên, trước tiên, bạn xóa cấu trúc email và mật khẩu khỏi req.body sự vật. Sau đó, bạn kiểm tra xem người dùng có tồn tại trong cơ sở dữ liệu của bạn hay không. Nếu người dùng không tồn tại trong cơ sở dữ liệu của bạn, bạn sẽ trả về với mã trạng thái 401.
Tiếp theo, sử dụng phương pháp so sánh của bcrypt, nhập mật khẩu mà người dùng đã cung cấp và mật khẩu băm mà bạn lấy từ cơ sở dữ liệu của mình. So sánh cả hai để xác nhận xem chúng có khớp nhau hay không. Nếu mật khẩu khớp, bạn sẽ trả về mã trạng thái 200 và thông báo thành công. Nếu không, bạn trả về mã trạng thái 401 và thông báo lỗi.
Cuối cùng, nhập bộ định tuyến vào của bạn app.js và sử dụng nó như một phần mềm trung gian cấp ứng dụng.
Điều này hoàn thành mô hình xác thực người dùng của bạn; giờ đây, người dùng có thể đăng ký và đăng nhập vào ứng dụng của bạn một cách an toàn.
Tầm quan trọng của xác thực người dùng
Xác thực người dùng đảm bảo rằng chỉ những người dùng hợp pháp mới có quyền truy cập vào ứng dụng của bạn. Nếu dữ liệu của bạn là cá nhân hoặc riêng tư theo bất kỳ cách nào, bạn nên thực hiện các bước để ngăn người dùng chưa được xác thực có quyền truy cập.