Copyright statement

Reprint please inform and indicate the source of the author: Tang Jinjian network nickname: Yu Yan nuggets Zhihu think no column: elegant front

First, pre-knowledge

  • Token-based authentication
  • Koajs Chinese document
  • Koa Framework tutorial

Second, the environment

  • Microsoft Visual Studio 2017Integrated development environment
  • Node. Js v8.9.4Javascript runtime environment

Three, start work, step by step to improve

1. Create a basic static resource server and infrastructure

Here is the basic code to implement a static server and a handle when token validation exceptions occur. Now we will gradually add the functions of registration, login and information under this basic code.

const path    = require('path');         // Used to process directory paths
const Koa     = require('koa');          // Web development framework
const serve   = require('koa-static');   // Static resource processing
const route   = require('koa-route');    // Routing middleware
const jwt     = require('jsonwebtoken'); // Used to sign and resolve 'tokens'
const jwtKoa  = require('koa-jwt');      // Used for routing permission control
const koaBody = require('koa-body');     // The query string is used to parse to 'ctx.request.query'
const app     = new Koa();

const website = {
    scheme: 'http'.host: 'localhost'.port: 1337.join: function () {
        return `The ${this.scheme}: / /The ${this.host}:The ${this.port}`}}/* JWT key */
const secret = 'secret';

/* Handle token verification exceptions, such as token expiration or token error */
app.use((ctx, next) = > {
    return next().catch((err) = > {
        if (err.status === 401) {
            ctx.status = 401;
            ctx.body = {
                ok: false.msg: err.originalError ? err.originalError.message : err.message
            }
        } else {
            throwerr; }}); });/* The query string is parsed to 'ctx.request.query' */
app.use(koaBody());

/* Route permission control */
// To-do list......

/* POST/API /register */
// To-do list......

/* GET/API /login Login */
// To-do list......

/* GET/API /info info */
// To-do list......


/* Static resource processing */
app.use(serve(path.join(__dirname, 'static')));
/* Listen on the server port */
app.listen(website.port, () => {
    console.log(`${website.join()}The server is started! `);
});
Copy the code

Next, we’ll add the implementation code under the comments for registration, login, and information.

2. Route permission control

Authentication is not required for registration, login interfaces, and other resources. Authentication is required for information interfaces.

/* Route permission control */
app.use(jwtKoa({ secret: secret }).unless({
    // Set the login and register interfaces without authentication
    path: [
        /^\/api\/login/, /^\/api\/register/, /^((? ! \/api).) * $/// Set resources other than private interfaces that do not require authentication access]}));Copy the code

3, registration,

/* POST/API /register */
app.use(route.post('/api/register'.async (ctx, next) => {
    const body = ctx.request.body;
    / * * body = {* user: 'royal Yan, * password:' 123456 '*} * /

    // Check whether the body. User and body. Password formats are correct
    // To-do list......

    // Check whether the user is registered
    // To-do list......

    // Save to database for new user
    // To-do list......

    // Check whether the registration is successful
    letRegistration successful =true;
    if(Whether the registration is successful) {// Return a JOSN successfully registered to the front-end
        return ctx.body = {
            ok: true.msg: 'Registration successful'.token: getToken({ user: body.user, password: body.password })
        }
    } else {
        // Return a failed JOSN to the front end
        return ctx.body = {
            ok: false.msg: 'Registration failed'}}}));/* Get a token */ with a duration of 4 hours
function getToken(payload = {}) {
    return jwt.sign(payload, secret, { expiresIn: '4h' });
}
Copy the code

3, login

/* GET/API /login Login */
app.use(route.get('/api/login'.async (ctx, next) => {
    const query = ctx.request.query;
    / * * query = {* user: 'royal Yan, * password:' 123456 '*} * /

    // Check whether the query.user and query.password formats are correct
    // To-do list......

    // Check whether the user is registered
    // To-do list......
    
    // Check whether the student id is correct
    // To-do list......
    
    return ctx.body = {
        ok: true.msg: 'Login successful'.token: getToken({ user: query.user, password: query.password })
    }
}));
Copy the code

4, the information

/* GET/API /info info */
app.use(route.get('/api/info'.async (ctx, next) => {
    // Front-end access will be attached to the token in the request header
    payload = getJWTPayload(ctx.headers.authorization)
    /* * payload = {* user: "yuyan ", * iAT: 1524042454, * exp: 1524056854 *} */

    // Query the information about the user in the database according to paypay. user
    // To-do list......
    const info = {
        name: 'royal Yan'.age: 10.sex: 'male'
    }
    letObtaining information successfully =true;
    if(Information obtained successfully) {return ctx.body = {
            ok: true.msg: 'Information obtained successfully'.data: info
        }
    } else {
        return ctx.body = {
            ok: false.msg: 'Failed to get information'}}}));/* Obtain the payload of the JWT using a token */
function getJWTPayload(token) {
    // Validate and parse JWT
    return jwt.verify(token.split(' ') [1], secret);
}
Copy the code

request
Authorization:Bearer [token]