Chức năng đăng nhập nodejs

Chức năng đăng nhập nodejs

Giới Thiệu Chung

Hôm nay mình sẽ hướng dẫn các bạn làm các chức năng signin, signup sử dụng các module như: Passport, flash,express-validator và bcrypt,
Giúp các bạn hiểu rõ và nắng vững các kiến thức về NodeJS cũng như ExpressJS.
Tìm hiểu về Authentication và xác thực đăng nhập bằng passport và xác minh bằng express-validator.

Bắt Đầu Thôi Nào

Cũng như các bài hướng dẫn trước thì bước đầu tiên thì các bạn phải tạo cho mình một folder trong folder đó là nơi mà chúng ta viết chương trình cho các chức năng.

Cài Đặt Và Thiết Lập

Cài đặt các module để thiết lập chương trình như:

  • npm install -save express-generator
    Module này nó sẽ giúp chúng ta tạo nhanh khung sườn cho ứng dụng
  • express --view=pug
    Nó sẽ tạo cho các bạn phần view engine và được setup là Pug
    Chức năng đăng nhập nodejs

    Các bạn có thể tùy chọn view engine mà mình thích các bạn tìm hiểu thêm
  • npm install nodemon --save
    Tự động reload lại server khi bạn thay đổi code
  • npm install connect-flash --save
    Lưu trữ và thông báo messages
  • npm install passport --save
    Là một trong những module phổ biến nhất của NodeJS hỗ trợ bạn authentication. Nó được thiết kế là một middleware hết sức linh hoạt.
  • npm install passport-local --save
    Module này cho phép bạn xác thực bằng tên user name và password trong các ứng dụng Node.js của bạn.
  • npm install bcrypt-nodejs -save
    Dùng để mã hóa mật khẩu hai chiều chống các hacker có thể đánh cắp.
  • npm install mongoose -save
    Mongoose là một Object Document Mapper (ODM). Điều này có nghĩa là Mongoose cho phép bạn định nghĩa các object (đối tượng) với một schema được định nghĩa rõ ràng.
  • npm install dotenv -save
    Dotenv là một module tải các biến môi trường từ tệp .env vào process.env. Lưu trữ cấu hình trong .env tách biệt với code để bảo mật thông tin.
  • npm install express-validator --save
    Dùng để kiểm tra xem bạn có nhập đúng email và xác minh xem mình có nhập đúng những yêu cầu về password như: phải chứa kí tự, chữ hoa hay trên 5 từ,..

Bắt Đầu Code Thôi Lào

Trong folder view bạn chọn index.pug. Trong index.pug bạn code như sau nhé:

Chức năng đăng nhập nodejs

Và đây là giao diện của trang chủ:
Chức năng đăng nhập nodejs

Trong folder view bạn chọn signin.pug. Trong signin.pug bạn code như sau nhé:
Chức năng đăng nhập nodejs

Và đây là giao diện trang Sign In:
Chức năng đăng nhập nodejs

Phía trên là giao diện của trang signup. Thì tương tự như trang signin, trang signup mình cũng làm như trên nhưng thay đổi một chút thôi.
Chức năng đăng nhập nodejs

Còn về phần css các bạn có thể css theo ý tưởng cũng như sở thích riêng mình, còn không các bạn có thể tham khảo code css của mình. Mình để ở link github ở dưới phần Lời Kết.

Thiết Lập Database

Cài đặt mongodb, các bạn tạo cho mình một file .env. Trong file này bạn bạn viết
MONGOURL=mongodb://localhost/sign-in
Trong file app.js các bạn khai báo module dotenv với module mongoose và tạo đường dẫn mongodb
// path database
mongoose.connect(process.env.MONGOURL,{useNewUrlParser:true, useUnifiedTopology: true });
Bây giờ mà mình muốn chạy được thì phải chạy database.

Chức năng đăng nhập nodejs

Định Nghĩa Schema Cho Mongoose Và Mã Hóa Password Trước Khi Lưu Vào Database

Các bạn tạo cho mình một folder là model trong folder bạn tạo cho mình file user.model.js
Trong file user.model.js các bạn cũng khai báo các module như mongoose và bcrypt-nodejs và tạo cho mình model của mongoose
Cấu hình schema cho user, mã hóa password và lưu các model của mongoose. Các bạn code như sau nhé:

Chức năng đăng nhập nodejs

Thiết Lập cho Passport

Các bạn sau khi mà install các module, thì các bạn nhớ khai báo module này vào trong file app.js nhé
var session = require('express-session')
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
app.use(session({
secret: 'adsa897adsa98bs',
resave: false,
saveUninitialized: false,
}))
app.use(flash());
app.use(passport.initialize())
app.use(passport.session());

Chú ý: Thứ tự cấu hình đối tượng passport rất quan trọng. Chúng ta khởi tạo đối tượng passport ở trên cùng bằng câu lệnh var passport = require('passport');. Sau đó chúng ta truyền đối tượng này vào logic trong file config/passport.js. Cuối cùng chúng ta đẩy đối tượng này vào router/users.js, trong file này nó sẽ sử dụng đối tượng passport đã được cấu hình.

Với file này chúng ta sẽ có một server chạy trên cổng 8000.
npm run devStart Sau đó truy cập bằng trình duyệt vào địa chỉ http://localhost:8000 chúng ta sẽ thấy ứng dụng của chúng ta. Bây giờ các bạn truy cập vào sẽ thấy giao diện trang signin,signup và trang index.

Routers router/users.js

Chúng ta sẽ thiết lập các router đơn giản. Chúng ta sẽ có những router sau:

  • Trang chủ (/)
  • Trang đăng nhập (/signin)
  • Trang đăng ký (/signup)
  • Xử lý cho request POST /signin
  • Xử lý cho request POST /signup
    Chức năng đăng nhập nodejs

Xác Thực Với Passport Local

Giờ chúng ta sẽ tạo user model, cấu hình passport cho xác thực local và sử dụng cấu hình passport cho việc xủa lý đăng nhập và đăng ký.

User Model

Với trường hợp local chúng ta sẽ dùng email và password. Bạn có thể thay đổi một vài trường mà bạn muốn. Bạn có thể sử dụng username và password cho việc xác thực tài khoản local.

Chức năng đăng nhập nodejs

Chúng ta đã hoàn thiện user model. Chúng ta “băm” (hashing) mật khẩu của user trước khi lưu nó vào database. Điều này có nghĩa là chúng ta sẽ không phải lưu mã hash vào trong bảng user.

Cấu Hình Passport Cho Tài Khoản Local

Tất các cấu hình cho passport sẽ được viết ở file config/passport.js. Chúng ta code tách riêng phần này ra ngoài file server, giống như routes và config. Viết riêng ra một file sẽ “clean” và ngắn gọn hơn.

Chúng ta tạo ra một đối tượng passport ở trong server.js, và tiếp theo đẩy nó và config/passport.js. Chúng ta sẽ cấu hình Strategy cho các trường hợp local. Đây cũng là tệp chúng ta thể hiện các hàm serializeUser và deserializeUser để lưu trữ thông tin user trong session.

Các bạn nên đọc qua document của passport docs để hiểu cách hoạt động của package này.

Xử Lý Yêu Cầu Đăng Nhập Và Đăng Ký

Chúng ta xử lý đăng nhập và đăng ký ở trong file config/passport.js. Thì các bạn làm theo như thế này nha:
// config/passport.js
// load các module
var passport = require('passport');
// load user model
var User = require('../models/user.model');
var LocalStrategy = require('passport-local').Strategy;
// passport session setup
// used to serialize the user for the session
sport.serializeUser(function(user, done){
done(null, user.id);
})
// used to deserialize the user
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
done(err, user);
})
})

// local sign-up
passport.use('local.signup',new LocalStrategy({
// mặc định local strategy sử dụng username và password
//chúng ta có thể cấu hình lại
usernameField:'email',
passwordField:'password',
passReqToCallback:true // cho phép chúng ta gửi reqest lại hàm callback
},function(req, email, password,done){

// Tìm một user theo email
// chúng ta kiểm tra xem user đã tồn tại hay không
User.findOne({ 'email': email }, function(err, user) {
if (err) { return done(err); }
if (user) {
return done(null, false, { message : 'Email is already in use.'})
}

// Nếu chưa user nào sử dụng email này
// tạo mới user
var newUser= new User();
// lưu thông tin cho tài khoản local
newUser.email= email;
newUser.password=
newUser.encryptPassword(password);
// lưu user
newUser.save(function(err, result){
if(err){
return done(err)
}
return done(null, newUser);
})
});
}
));

Giờ chúng ta đã cung cấp một Strategy tới passport với tên local.signup. Chúng ta sẽ sử dụng Strategy này cho việc xử lý form đăng ký. Mở lại file router/users.js và thêm vào xử lý cho request POST /signup
//router/users.js
...
// Xử lý thông tin khi có người đăng ký
app.post('/signup', passport.authenticate('local.signup', {
successRedirect: '/signin', // chuyển hướng tới trang đăng nhập sau khi đăng ký
failureRedirect: '/signup', // trở lại trang đăng ký nếu có lỗi
failureFlash: true // allow flash messages
}));
...

Kiểm Tra Đăng Ký

Với những gì chúng ta đã cấu hình cho passport. Nó sẽ sử dụng config của chúng ta và form đăng ký có thể hoạt động. Thì chúng ta require passport vào file app.js để xác thực.

// app.js
...
require('./config/passport'); // pass passport for configuration
...

Giờ chúng ta đã có passport, routes, tiến hành test form đăng ký. Trên trình duyệt bạn truy cập theo địa chỉ http://localhost:8000/signup điền thông tin vào form và submit.

Nếu mọi thứ theo kế hoạch, bạn sẽ được đăng nhập, thông tin user sẽ được lưu trong session và bạn được chuyển tới trang /signin để đăng nhập.
Nếu bạn nhìn vào database, chúng ta sẽ thấy thông tin user được tạo:

Chức năng đăng nhập nodejs

Để quản lý mongodb các bạn có thể dùng Robomongo. Cài đặt và kết nối vào db của mình.
Với những user đã được đăng ký, giờ chúng ta làm chức năng đăng nhập.

Cũng tương tự như chức năng đăng ký. Chúng ta sẽ thêm một Strategy vào file config/passport.js và sửa file router/users.js
// config/passport.js
// local sign-in
passport.use('local.signin',new LocalStrategy({
// mặc định local strategy sử dụng username và password chúng ta có thể cấu hình lại
usernameField:'email',
passwordField:'password',
passReqToCallback:true
// cho phép chúng ta gửi reqest lại hàm callback
},function(req, email, password,done)
{

// tìm một user với email
// chúng ta sẽ kiểm tra xem user có thể đăng nhập không
User.findOne({ 'email': email }, function(err, user) {
if (err) { return done(err); }
// Nếu không có user thì in ra lỗi
if (!user) {
return done(null, false, { message : 'Not user found'})
}
if(!user.validPassword(password)){
return done(null,false,{message:'Wrong password'})
}
return done(null, user);
});
}
));

Trong file // router/users.js
...
// Xử lý thông tin khi có người thực hiện đăng nhập
app.post('/signin', passport.authenticate("local.signin", {
successRedirect : '/', // Khi bạn điền đúng thông tin đăng nhập thì nó sẽ chuyển hướng bạn đến trang chủ
failureRedirect : '/signin',// trở lại trang đăng nhập nếu có lỗi
failureFlash : true
}));
...

Nếu bạn đăng nhập với một tài khoản email chưa được đăng ký thì bạn sẽ nhận được thông báo lỗi. Tương tự với password.

Chức năng đăng nhập nodejs

Validator Trang Đăng Ký

express-validator là một tập hợp các middlewares express.js các chức năng của xác thực của validator.js.
Tại sao mình không nói là validator trang đăng nhập và đăng ký mà chỉ một mình đăng ký. Bởi vì trang đăng nhập chức năng chính của nó là xác thực xem bạn có nhập đúng password và email mà các bạn có đăng ký hay không.

Còn trang đăng ký chúng ta phải xác thực xem bạn có nhập đúng email hay không và xem email có tồn tại, password phải nhập đúng số kí tự bắt buộc để tăng khả năng bảo mật tài khoản,..

Trong file router/users.js
Các bạn load package express-validator
const { check, validationResult } = require('express-validator');
Các bạn cấu hình cho express-validator như này nhé:

Chức năng đăng nhập nodejs

Ví dụ: khi chúng ta nhập chưa đủ kí tự password thì xem nó báo lỗi như thế nào nhé
Chức năng đăng nhập nodejs


Lời Kết

Vậy Là Xong Chức Năng Đăng Nhập Sử Dụng NodeJS Và MongoDB rồi nhé. Các bạn tự code và xem kết quả nhé, khi làm xong bài này các bạn sẽ nắm được kiến thức về Authentication.

Mình có push code lên github các bạn tham khảo.

Nếu mọi người cảm thấy bài viết này hay thì có thể ủng hộ mình để mình có động lực để ra những bài topic hay và chất lượng hơn ủng hộ mình tại đây nha.

Chúc Các Bạn Thành Công!!