This article describes how to build a simple JWT-BASED user registration, login and authentication application using Hapi.
Hapi is an open source node.js-based application framework for building applications and services. It is designed to allow developers to focus on developing reusable application business logic and provide developers with the infrastructure needed to build application business logic.
Hapi is a Web framework developed by walmart’s technology team that has the following advantages:
- High performance – HaPI developers adhere to Benchmark Driven Development
- High security and lightweight
- scalability
- Built-in cache, Redis, MongoDB, Memcached
- Core code is 100% tested
- Built in end-to-end testing
- Core functions are built in, and other features are presented in the form of plug-ins.
As a result, haPI performs well even in black Friday shopping events and can be used to efficiently create a set of interfaces that support RESTful specifications.
Create a project
- The project structure
➜ hapi mkdir userLogin
➜ hapi cdUserLogin ➜ userLogin NPM init - y demonstrate the to/Users/huangyuhui/Desktop/hapi/userLogin/package. The json: {"name": "userLogin"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": []."author": ""."license": "ISC"
}
Copy the code
2. Install dependencies
➜ userLogin npm install hapi mongoose nodemon jsonwebtoken bcrypt
Copy the code
Add the startup script
Modify the packge.json file by adding code to the “scripts” object:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."start": "nodemon server.js"
},
Copy the code
Create a user model
- Created in the project root directory
models
folder - in
models
Create a folderUser.js
file
const mongoose = require('mongoose')
const Schema = mongoose.Schema
// Create Schema
const UserSchema = new Schema({
first_name: {
type: String
},
last_name: {
type: String
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
})
module.exports = User = mongoose.model('users', UserSchema)
Copy the code
Create a service
- Created in the project root directory
server.js
file
'use strict'
const Hapi = require('hapi'// introduce hapijs const mongoose = require('mongoose'// mongoDB database // create server const server = new hapi. server ({host:'localhost'// routes: {cors:true}}) // Connect to mongoDB database server.app.db = mongoose. Connect ('mongodb://localhost/mernloginreg', {
useNewUrlParser: true,
useUnifiedTopology: true}) const init = async () => {await server // routes.register ({plugin: require())'./routes/Users'}, {routes: {// set the default route prefix prefix:'/users'}}). Catch (err => {console.log(err)}) // Start service await server.start() // Prompt service start message console.log(' server running at:${server.info.uri}`)
}
init()
Copy the code
6. Create routing plug-ins
- Created in the project root directory
routes
folder - in
routes
Create a folderUsers.js
file
'use strict'
const jwt = require('jsonwebtoken'//token issue and validation const bcrypt = require('bcrypt'// string encryption const User = require('.. /models/User'// import user model const mongoose = require('mongoose'// Run process.env.secret_key ='secret'Exports. plugin = {register: (server, options, next) => {// Define user registration interface server.route({method:'POST',
path: '/register'Handler: (req, h) => {// Set the registration timelet today = new Date()
letM = today.getMinutes() -today.getTimezoneOffset () today.setminutes () today.setminutes () const userData = { first_name: req.payload.first_name, last_name: req.payload.last_name, email: req.payload.email, password: Req.payload-password, date: today} // Check whether the database has the same email field contentreturnUser.findone ({email: req.payload-email}). Then (User => {// If no User is found, the User is a new registered Userif(! Bcrypt. hash(req.paypay. password, 10, (err,) {// Encrypt the password entered by the client in plaintext.hash) => {
userData.password = hash// Write the registered user to the databasereturnUser.create(userData). Then (User => {// The registration success message is displayedreturn {
status: user.email + ' Registered! '}}). Catch (err => {// Returns an error messagereturn 'error: '+ err})}) // Returns the user registrationreturn userData
} else{// If the database has the same email content, return that the user already exists, do not write again.return {
error: 'User already exists'}}}). Catch (err => {// Error messagereturn 'error: '+ err})}}), // Define user login interface server.route({method:'POST',
path: '/login'Handler: (req, h) => {// Find the database record based on the requested email contentreturn User.findOne({
email: req.payload.email
})
.then(user => {
if(user) {// If the email content of the request exists, proceed by comparing the password value of the requestif(bcrypt.compareSync(req.payload.password, User.password)) {// If the requested password is the same as the password recorded in the database // Define the content object to issue the token const payload = {id: user._id, first_name: User.first_name, last_name: user.last_name, email: user.email} // Issue a tokenletToken = jwt.sign(payload, process.env.secret_key, {// Set token validity period expiresIn: 1440}) // Returns the token string valuereturn token
} else{// If the requested user password does not exist, return the user does not existreturn {
error: 'User does not exist'}}}else{// If the requested user email does not exist, return the user does not existreturn {
error: 'User does not exist'
}
}
})
.catch(err => {
return{error: err}})}}), // Obtain user information server.route({method:'GET',
path: '/profile', handler: (req, h) => {// Verify the token value in the request header, Reduction of token content object var decoded = JWT. Verify (the req. Headers. Authorization, and process. The env. SECRET_KEY) / / data in the database according to the token object id valuereturnUser.findOne({ _id: Mongoose.types.objectid (decoded.id)}). Then (user => {console.log(user) // If the user is found, the user information is returned. Otherwise, the user information cannot be foundif (user) {
return user
} else {
return 'User does not exist'
}
})
.catch(err => {
return 'error: ' + err
})
}
})
},
name: 'users'// Custom plug-in name}Copy the code
7. Interface test
Start the service:
➜ userLogin NPM start > [email protected] start/Users/huangyuhui/Desktop/hapi/userLogin > nodemon server js [nodemon] 2.0.2 [nodemon] to restart at any time, enter 'rs' watching dir(s): *.* [nodemon] watching Extensions: js,mjs,json [nodemon] starting `node server.js` Server running at: http://localhost:5000Copy the code
-
User registration
-
The user login
-
Obtaining User information
Denver annual essay | 2019 technical way with me The campaign is under way…