JWT
Json Web Token (JWT) is an open jSON-based standard ([(RFC 7519]) implemented for the transfer of declarations between network application environments. The token is designed to be compact and secure, especially suitable for single sign-on (SSO) scenarios in distributed sites. The JWT declaration is generally used to pass authenticated user identity information between the identity provider and the service provider to obtain resources from the resource server, and to add some additional declaration information necessary for other business logic. The token can also be used directly for authentication or can be encrypted.
JWT certification process
- The user requests the server using a username and password
- The server authenticates the user’s information
- The server sends the user a token through authentication
- The client stores the token and supplies it with each request
- The server validates the token value and returns data
The main difference between session-based and JWT-BASED approaches is where the user’s state is stored. The Session is stored on the server, while the JWT is stored on the client.
Once a JWT is issued, it remains valid until it expires and cannot be abandoned.
Eggjs implements the signing and authentication of tokens
Install dependencies
# jwt
npm i egg-jwt
# password encryption
bcryptjs
# Data verification
egg-validate
Copy the code
The use of plug-in
config/plugin.js
jwt: {
enable: true.package: 'egg-jwt',},validate: {
enable: true.package: 'egg-validate',},Copy the code
Modifying a Configuration File
config/config.default.js
// jwt
config.jwt = {
secret: '123456'.expiresIn: '24h'};/ / parameters
config.validate = {
enable: true.package: 'egg-validate'};// Password encryption
config.bcrypt = {
saltRounds: 10};Copy the code
User registration, login interface development
Creating a user model
app/model/user.js
'use strict';
module.exports = app= > {
const { STRING, INTEGER, DECIMAL, DATE } = app.Sequelize;
const User = app.model.define('users', {
id: { type: INTEGER, primaryKey: true.autoIncrement: true },
userName: {
type: STRING,
allowNull: false.unique: true.comment: 'Username, unique',},passWord: STRING,
});
return User;
};
Copy the code
user Controller
app/controller/user.js
// Verify user registration parameters
const vUser = {
userName: { type: 'string'.required: true },
passWord: { type: 'string'.required: true}};/ /...
class UserController extends Controller {
// User registration
async rigist() {
const { ctx } = this;
// Accept and validate parameters
ctx.validate(vUser, ctx.request.body);
// Check whether the user name is the same
const users = await ctx.service.user.checkUserName(ctx.request.body);
if (users[0]) {
ctx.body = { status: false.msg: 'Username already exists'.data: users };
return;
}
await ctx.service.user.Rigist(ctx.request.body);
ctx.body = { status: true.msg: 'Registration successful' };
}
// The user logs in
async login() {
const { ctx } = this;
// Accept and validate parameters
ctx.validate(vUser, ctx.request.body);
const data = await ctx.service.user.Login(ctx.request.body);
if(! data) { ctx.status =401;
ctx.body = { status: false.msg: 'Wrong username or password' };
return;
}
ctx.body = { status: true.msg: 'Successful landing', data }; }}module.exports = UserController;
Copy the code
user Service
app/service/user.js
const bcrypt = require('bcryptjs');
/ /...
// Check the user name
async checkUserName(query) {
const { userName } = query;
const users = await this.ctx.model.User.findAll({
attributes: [ 'userName'].where: { userName },
});
return users;
}
// User registration
async Rigist(body) {
const { userName, passWord } = body;
// Encrypt the password
const hash = bcrypt.hashSync(passWord, this.config.bcrypt.saltRounds);
const user = await this.ctx.model.User.create({ userName, passWord: hash });
return user;
}
// The user logs in
async Login(body) {
const { userName, passWord } = body;
const user = await this.ctx.model.User.findOne({
where: { userName },
});
if(! user)return {};
const match = await bcrypt.compare(passWord, user.passWord);
if (match) {
const { id, userName } = user;
// Get JWT configuration
const { jwt: { secret, expiresIn } } = this.app.config;
/ / token is generated
const token = this.app.jwt.sign({
id, userName,
}, secret, { expiresIn });
return{ userName, token }; }}Copy the code
router
app/router.js
router.post('/api/v1/user/rigist', controller.user.rigist); // User registration
router.post('/api/v1/user/login', controller.user.login); // The user logs in
// Add JWT middleware to the route to use JWT authentication
router.put('/api/v1/user/:id', app.jwt, controller.user.update); // Modify user information
Copy the code
Obtaining token Content
If the interface uses app.jWT middleware
const userToken = this.ctx.state.user;
// Get the content id, userName,
Copy the code
If the interface does not use app.jwt middleware, this.ctx.state.user cannot be retrieved;
Some interfaces may or may not be logged in, and data acquisition is different.
In this case, you need to encapsulate the method to resolve the token
app/extend/utils.js
'use strict';
function getTokenInfo(jwt, auth, secret) {
// Determine whether the request header contains the token
if (
auth.authorization &&
auth.authorization.split(' ') [0= = ='Bearer'
) {
const token = auth.authorization.split(' ') [1];
let decode = ' ';
if (token) {
decode = jwt.verify(token, secret);
}
return decode;
}
return;
}
module.exports = {
getTokenInfo,
};
Copy the code
Use in service
const { jwt: { secret } } = this.app.config;
// Resolve the token if there is one
const authInfo = getTokenInfo(this.ctx.app.jwt, this.ctx.headers, secret);
if (authInfo) {
// Get the token content
// authInfo.id authInfo.userName
}
Copy the code