Hướng dẫn login nodejs - đăng nhập nodejs

Hướng dẫn login nodejs - đă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.
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
    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 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
    Nó sẽ tạo cho các bạn phần view engine và được setup là Pug
    Hướng dẫn login nodejs - đă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
    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
    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.
    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.
    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.
    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.
    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.
    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ừ,..
    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é:Và đây là giao diện của trang chủ: Trong folder view bạn chọn signin.pug. Trong signin.pug bạn code như sau nhé:Và đây là giao diện trang Sign In: 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. 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.

Hướng dẫn login nodejs - đăng nhập nodejs

Và đây là giao diện của trang chủ:
Hướng dẫn login nodejs - đăng nhập nodejs

Trong folder view bạn chọn signin.pug. Trong signin.pug bạn code như sau nhé:
Hướng dẫn login nodejs - đăng nhập nodejs

Và đây là giao diện trang Sign In:
Hướng dẫn login nodejs - đă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.
Hướng dẫn login nodejs - đă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ếtMONGOURL=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 databasemongoose.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.
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.

Hướng dẫn login nodejs - đă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é:
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é:

Hướng dẫn login nodejs - đă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());
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.
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
    Hướng dẫn login nodejs - đă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ú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.

Hướng dẫn login nodejs - đă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.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 })); ...
// 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.
...
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:
Nếu bạn nhìn vào database, chúng ta sẽ thấy thông tin user được tạo:

Hướng dẫn login nodejs - đă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.
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-inpassport.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); }); } ));
// 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.
...
// 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.

Hướng dẫn login nodejs - đă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.
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-validatorconst { check, validationResult } = require('express-validator'); Các bạn cấu hình cho express-validator như này nhé: 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é
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é:

Hướng dẫn login nodejs - đă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é
Hướng dẫn login nodejs - đă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!!