One of the easiest ways to write a series of articles is to get halfway through and then run out of ideas. One factor is laziness; One factor is that after sorting out the knowledge of user module these days, I found that there are too many contents to write, and after going deep into Google, I found that many contents are unknown to me, so I don’t know how to write.

Common operations related to the user module include registration and login, information modification, and logout

User table design

In a system, user module is the most basic and the most important. If only one login method is considered, the users table can do everything with a single Users table. But the reality is that there are many login methods, such as: account password login, wechat, QQ, Weibo log, mobile phone number, email login. And a user can use the account password after logging in and then associated with wechat, QQ, Weibo, then can directly use wechat, QQ, Weibo denglu; How to ensure the design of user tables becomes critical.

Reference:

  1. Extensible user table design
  2. Designing an extensible user Login System (1)
  3. User system design and implementation
  4. Design of multi-platform unified user system

From the above blog posts, we can design the user table as user_Base, user_Auth, and user_extends.

User base tables include UID, user_Role, user_name, Avatar, password, Signature, birthday, and gender

User authorization table: ID, UID, identity_type, Identifier, certificate, etc

User extended tables: ID, UID, device_name, device_id, vendor, client_NAME, client_version, etc

The above user table design can refer to: user system design and implementation

Ps: I did not consider so much about the design of the user table of this project at that time. I only considered the design of wechat small program end. I left a hole for myself first and then improved the project. First, introduce the current implementation.

My current implementation steps are as follows:

Create user.js under the APP/Models package: related fields of the user table and operations of the user table

User.init({
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    nickname: Sequelize.STRING,
    email: {
        typeSTRING(128) : sequelize.string (128), // Insert duplicate values after adding unique constraint unique:true
    },
    password: {
        type: Sequelize.STRING,
        setConst salt = bcrypt.gensaltsync (10) const PSW = bcrypt.hashsync (val, // Set password value this.setDatavalue ('password', psw)
        }
    },
    openid: {
        type: Sequelize.STRING(64),
        unique: true
    },
    gender: Sequelize.INTEGER,
    balance: Sequelize.INTEGER,
    avatar_url: Sequelize.STRING,
    city: Sequelize.STRING,
    country: Sequelize.STRING,
    province: Sequelize.STRING
}, {
    sequelize,
    tableName: 'users'
})

module.exports = {
    User
}
Copy the code

Log in

registered

Wechat applet does not require registration, but can be directly logged in using wechat authorization.

In this case, a user registers with an email address, user name, and password on the Web or App.

Create user.js from app/ API /v1:

/** * router.post('/register', async (CTX) => {const v = await new RegisterValidator().validate(CTX) //'body.email'),
        password: v.get('body.password2'),
        nickname: v.get('body.nickname'} // Use Sequlize to save to database await user.create (User) success()}) module.exports = routerCopy the code

Call: http://192.168.*.***:3000/v1/user/register, fill in your email, username, and password in the form, and pass the result to the API

The login

Log in using your account (email) and password

/** * Email login: If the user does not exist, the system will prompt that the account does not exist. If the user does exist, the system will verify the user information and return token * @param {account} account * @param {password} secret */ asyncfunction emailLogin(account, secret) {
    const user = await User.verifyEmailPassword(account, secret)
    return token = generateToken(user.id, Auth.USER)
}
Copy the code

Create wx.js in app/service package: Obtain the login token

Class WXManager {/** * applets login * @param {applets pass code} code * @param {applets public user information} userInfo */ static async codeToToken(code, userInfo) { const url = util.format(global.config.wx.loginUrl, global.config.wx.appId, Global. Config. Wx appSecret, code) / / call WeChat provided interfaces const result = await axios. Get (url)if(result.status ! == 200) { throw new global.errs.AuthFailed('OpenID fetch failed'Const errcode = result.data. Errcode const errmsg = result.data. Errmsgif (errcode){
            throw new global.errs.AuthFailed('OpenID fetch failed :'+errmsg)} // openID // file user uid OpenID length // openID // Whether the user exists, for example, the token has expiredlet user = await User.getUserByOpenid(result.data.openid)
        if(! user){ user = await User.registerByOpenid(result.data.openid, userInfo) }return generateToken(user.id, Auth.USER)
    }
}

module.exports = {
    WXManager
}
Copy the code

(1) Account password login call: http://192.168.*.***:3000/v1/token, fill in the form email, password, and then send the result to API; (2) Applet login call: log in the applet first, then call http://192.168.*.***:3000/v1/token, and send the code provided by the applet to the API

Both account password login and wechat applet login return token mainly for API authentication, login state is maintained under core package create util.js: generate token utility class

/** * generateToken with JWT * @param {user id} uid * @param {user permission} scope */ const generateToken =function(uid, The scope) {const secretKey = global. Config. Security. The secretKey const expiresIn = global. Config. Security. ExpiresIn / / in Const token = jwt.sign({uid, scope}, secretKey, {expiresIn: expiresIn})return token
}

module.exports = {
    generateToken,
}
Copy the code

Introductions of JWT can view before I write the article: full stack project | | small bookcase server development – JWT explanation, or this article: more detailed analysis of JWT

Modify the information

To change the user information, run the Update command. To change the password, clear the local login status and log in again.

Specific modification information, the subsequent implementation of the interface to fill.

Log out

How to log out when using JWT

The main ways described in the article are as follows:

  • Set a reasonable expiration time for the token
  • After you log out, the client is deletedtoken
  • The database store is no longer valid and has expiredtoken
  • Maintain blacklists on the server side using Redis- Wikipedia

Maintaining the blacklist may cause the blacklist to be too long. You can check whether the token expires and delete the token automatically.

This project only deletes the token from the client to log out.

For other processing methods, please refer to:

  • How to invalidate JWT Token when logging out/changing password?
  • Solution to invalidate JWT by logging out
  • JWT super detailed analysis – other issues of JWT

For enquiries, please add wechat: gently.