From zero to deployment: using Vue and Express to implement mini full-stack e-commerce applications (9): using Authing to create an enterprise-level user system with WeChat login

Posted May 26, 202021 min read

If you think we have written well, remember like + follow + comment Sanlian, encourage us to write better tutorials ?

If you want to build an enterprise user system that supports WeChat login in the applet, you can learn another article from the Tuque community: Taro applet development large-scale combat(9):use Authing to create an enterprise user system with WeChat login

In the previous mini e-commerce application, our website lacked a key component:the user authentication system, including the corresponding configuration of login, registration, and rights management. It is certainly feasible to implement these functions by hand, but for a lean team, it is more wise to choose a reliable identity authentication service(IDaaS), which not only provides comprehensive and rich identity authentication and user authentication functions, but also ensures Follow best security practices and excellent scalability. In this tutorial, we will take you by hand to quickly integrate the Authing user authentication module into the mini e-commerce application completed before this series, providing Safe identity authentication experience.

First, let's take a look at the effect of the overall user system after access:

Add user interface and routing

After understanding the effect, we have prepared for you the mini e-commerce code after reconstruction, you can Clone this code, and then follow the tutorial to supplement the integration of user system needs:

git clone -b auth-start https://github.com/tuture-dev/vue-online-shop-frontend.git
# Or download the warehouse on Gitee
git clone -b auth-start https://gitee.com/tuture/vue-online-shop-frontend.git

After the code is downloaded, create the user directory in the client/src/pages directory, and we will implement all the pages related to the user system in the next time.

Tips
This tutorial uses the Vue 2.x version, but the core of this tutorial is to integrate the user system through Authing. We have not used much knowledge about Vue.

First, we create the Index.vue user homepage component under the user page directory, the code is as follows:

<template>
  <div>
    <div class = "container">
      <div class = "container">
        <h1 class = "user-title">
          <router-link to = "/" tag = "div"> Login/Registration </router-link>
        </h1>
        <router-view />
      </div>
    </div>
  </div>
</template>

<style>
.user-title:hover {
  cursor:pointer;
}

.container {
  margin-top:40px;
}
</style>

Then create Login.vue login component, the code is as follows:

<template>
  <div id = "login-form"> User login </div>
</template>

<script>
export default {};
</script>

Then create Setting.vue setting component, the code is as follows:

<template>
  <div> settings </div>
</template>

<script>
export default {
  data() {
    return {
      model:{manufacturer:{name:"", _id:""}}
    };
  },
  mounted() {}
};
</script>

Configure center routing

The last is to integrate the user system related pages defined above in the routing, modify the client/src/router/index.js code as follows:

//...
import UserIndex from "@/pages/user/Index";
import Login from "@/pages/user/Login";
import Setting from "@/pages/user/Setting";

Vue.use(Router);

const router = new Router({
  routes:[
    {
      path:"/",
      name:"Home",
      component:Home
    },
    {
      path:"/admin",
      name:"Admin",
      component:Index,
      children:[
        {
          path:"new",
          name:"New",
          component:New
        },
        {
          path:"",
          name:"Products",
          component:Products
        },
        {
          path:"edit /:id",
          name:"Edit",
          component:Edit
        },
        {
          path:"manufacturers",
          name:"Manufacturers",
          component:Manufacturers
        },
        {
          path:"manufacturers/new",
          name:"NewManufacturers",
          component:NewManufacturers
        },
        {
          path:"manufacturers/edit /:id",
          name:"EditManufacturers",
          component:EditManufacturers
        }
     ]
    },
    {
      path:"/cart",
      name:"Cart",
      component:Cart
    },
    {
      path:"/detail /:id",
      name:"Detail",
      component:Detail
    },
    {
      path:"/user",
      name:"User",
      component:UserIndex,
      children:[
        {
          path:"login",
          name:"Login",
          component:Login
        },
        {
          path:"settings",
          name:"Settings",
          component:Setting
        }
     ]
    }
 ]
});

export default router;

Run the project, click on the login or registration in the upper right corner should be able to successfully jump to the login page(although it is still very simple now):

OK, let's implement each page specifically ~

Use Authing to access the user system

In this step, we will officially use Authing to access the user system. Authing is an excellent domestic identity authentication cloud, which allows us to easily integrate the logic related to identity authentication. Quite adequate.

First, let us visit the official Authing website and click the login button in the upper right corner, as shown below:

image.png
After entering the login page, we enter the account name and password, and an account will be created directly for us:

After entering the console, let us create a new User Pool (as the name implies, Is used to manage and store a series of user data and information), as shown below:

When creating a user pool, after entering the user pool name and exclusive domain name we want, select the type as Web, and finally click, our first user pool is created. Click the "Basic Configuration" bookmark to view some key information of the user pool you just created, especially the user pool ID, as shown in the following figure:

NOTE
For subsequent application development, replace all user pool IDs(userPoolId) with the real IDs of your accounts.

Configure Vuex Mutations and Store

Since our application uses Vuex to solve state management problems, we first need to define authentication related mutations. Here we define two new mutations:

  • SET_USER:Set user identity data
  • LOGOUT:log out

Add the above three mutation constants in client/src/store/mutation-types.js, the code is as follows:

export const ALL_PRODUCTS = "ALL_PRODUCTS";
export const ALL_PRODUCTS_SUCCESS = "ALL_PRODUCTS_SUCCESS";

export const PRODUCT_BY_ID = "PRODUCT_BY_ID";
export const PRODUCT_BY_ID_SUCCESS = "PRODUCT_BY_ID_SUCCESS";

export const ADD_PRODUCT = "ADD_PRODUCT";
export const ADD_PRODUCT_SUCCESS = "ADD_PRODUCT_SUCCESS";

export const UPDATE_PRODUCT = "UPDATE_PRODUCT";
export const UPDATE_PRODUCT_SUCCESS = "UPDATE_PRODUCT_SUCCESS";

export const REMOVE_PRODUCT = "REMOVE_PRODUCT";
export const REMOVE_PRODUCT_SUCCESS = "REMOVE_PRODUCT_SUCCESS";

export const ADD_TO_CART = "ADD_TO_CART";
export const REMOVE_FROM_CART = "REMOVE_FROM_CART";

export const ALL_MANUFACTURERS = "ALL_MANUFACTURER";
export const ALL_MANUFACTURERS_SUCCESS = "ALL_MANUFACTURER_S";

export const MANUFACTURER_BY_ID = "MANUFACTURER_BY_ID";
export const MANUFACTURER_BY_ID_SUCCESS = "MANUFACTURER_BY_ID_SUCCESS";

export const ADD_MANUFACTURER = "ADD_MANUFACTURER";
export const ADD_MANUFACTURER_SUCCESS = "ADD_MANUFACTURER_SUCCESS";

export const UPDATE_MANUFACTURER = "UPDATE_MANUFACTURER";
export const UPDATE_MANUFACTURER_SUCCESS = "UPDATE_MANUFACTURER_SUCCESS";

export const REMOVE_MANUFACTURER = "REMOVE_MANUFACTURER";
export const REMOVE_MANUFACTURER_SUCCESS = "REMOVE_MANUFACTURER_SUCCESS";

export const SET_USER = "SET_USER";
export const UPDATE_USER = "UPDATE_USER";
export const LOGOUT = "LOGOUT";

Then we implement the above-defined user-related mutation in client/src/store/mutations.js, the code is as follows:

//...
  UPDATE_MANUFACTURER_SUCCESS,
  REMOVE_MANUFACTURER,
  REMOVE_MANUFACTURER_SUCCESS,
  SET_USER,
  UPDATE_USER,
  LOGOUT
} from "./mutation-types";
import {Message} from "element-ui";

export const userMutations = {
  [SET_USER](state, payload) {
    state.user = payload;
  },
  [LOGOUT](state) {
    state.user = {};
  }
};

export const productMutations = {
  [ALL_PRODUCTS](state) {
    //...
    state.showLoader = false;

    const {productId} = payload;
    state.products = state.products.filter(
      product => product._id! == productId
   );
  },
  [UPDATE_PRODUCT](state) {
    state.showLoader = true;
  //...

    const {product:newProduct} = payload;
    state.product = newProduct;
    state.products = state.products.map(product => {
      if(product._id === newProduct._id) {
        return newProduct;
      }
      //...
    const {product} = payload;
    state.cart.push(product);
    Message({
      message:"Congratulations, you have successfully joined the shopping cart!",
      type:"success"
    });
  },
  [REMOVE_FROM_CART](state, payload) {
    const {productId} = payload;
    state.cart = state.cart.filter(product => product._id! == productId);
    Message({
      message:"Congratulations, you have successfully removed the shopping cart!",
      type:"success"
    });
  }
};

export const manufacturerMutations = {
  //...
    state.showLoader = false;

    const {manufacturerId} = payload;
    state.manufacturers = state.manufacturers.filter(
      manufacturer => manufacturer._id! == manufacturerId
   );
  },
  [UPDATE_MANUFACTURER](state) {
    state.showLoader = true;
  //...
    const {manufacturer} = payload;
    state.manufacturers = state.manufacturers.concat(manufacturer);
  }
};

Finally, we integrate the corresponding state and mutation in the Vuex Store, modify client/src/store/index.js, the code is as follows:

//...
import {productGetters, manufacturerGetters} from "./getters";
import {
  productMutations,
  cartMutations,
  manufacturerMutations,
  userMutations
} from "./mutations";
import {productActions, manufacturerActions} from "./actions";

Vue.use(Vuex);

export default new Vuex.Store({
  strict:true,
  state:{
    //...
    //userInfo
    user:{}
  },
  mutations:{
    ... productMutations,
    ... cartMutations,
    ... manufacturerMutations,
    ... userMutations
  },
  //...
});

Integrate user logic in the root component App

Let's open the root component client/src/App.vue and add a mounted method to it, so that the user identity data is obtained and checked when the entire application is started. The modified code is as follows:

//...

<script>
export default {
  name:"App",
  mounted() {
    const userInfo = localStorage.getItem("userInfo");

    if(userInfo) {
      this. $store.commit("SET_USER", JSON.parse(userInfo));
    }
  }
};
</script>

//...

As you can see, we check whether there is userInfo data from localStorage, and if so, save the user identity data into the state through SET_USER Mutation.

Integrate user logic in the header component Header

Open the head component client/src/components/Header.vue, we add the logic related to the user system in it, and modify the code as follows:

//...

<script>
export default {
  props:["activeIndex"],
  data() {
    return {
      model:{manufacturer:{name:"", _id:""}}
    };
  },
  computed:{
    isLogged() {
      let token = this. $store.state.user.token;

      return !! token;
    },
    avatar() {
      let photo = this. $store.state.user.photo;

      return photo;
    }
  },
  methods:{
    handleLogout() {
      localStorage.removeItem("token");
      localStorage.removeItem("userInfo");
      this. $store.commit("LOGOUT");
    }
  }
};
</script>

As you can see, we mainly made the following changes:

  • Changed isLogged from the original data to a calculated attribute, and determine whether to log in by obtaining the existence of token from the Vuex Store
  • Added avatar calculation attribute to get user avatar from Store
  • Implemented the handleLogout method to handle logout logic, including removing token and userInfo data from localStorage and initiating a LOGOUT mutation to update the status of the store

Login page through Authing Guard

Guard is an embeddable login form launched by Authing, which allows us to integrate login and registration functions for the entire application with a few lines of code The effect is as follows:

The overall effect is still very good, and we can easily customize through some configuration items, let's take a look at how to achieve it.

First, we integrate Authing Guard by introducing the Authing UMD build file. Introduced through the script tag in the client/index.html file:

<! DOCTYPE html>
<html>
  <head>
    <meta charset = "utf-8" />
    <meta name = "viewport" content = "width = device-width, initial-scale = 1.0" />
    <title> vue-online-shop </title>
  </head>
  <body>
    <div id = "app"> </div>
    <!-built files will be auto injected->
    <script src = "https://cdn.jsdelivr.net/npm/@authing/guard/dist/Guard.umd.min.js"> </script>
  </body>
</html>

Then open the login page component client/src/pages/user/Login.vue and modify the code as follows:

<template>
  <div id = "login-form"> </div>
</template>

<script>
export default {
  data() {
    return {
      model:{manufacturer:{name:"", _id:""}}
    };
  },
  mounted() {
    const appId = "";
    const userPoolId = "";
    const domain = "https://tuture-first.authing.co";

    const form = new Guard(userPoolId, {
      logo:"https://tuture.co/images/avatar.png",
      title:"Tuque Full Stack Mini E-Commerce",
      mountId:"login-form",
      hideClose:true
    });

    const that = this;

    form.on("authenticated", userInfo => {
      that. $store.commit("SET_USER", userInfo);
      localStorage.setItem("token", JSON.stringify(userInfo.token));
      localStorage.setItem("userInfo", JSON.stringify(userInfo));

      that. $router.push("/");
    });
  }
};
</script>

We initialize the Guard instance in the mounted lifecycle method. When initializing the Guard instance, the first parameter is the user pool ID(_ Remember to change to your own user pool ID! _), which can be obtained through the Authing console, and the second parameter is the Guard Some option parameters:

  • logo is a link to the Logo picture of our entire website
  • title is the title of the entire login form
  • mountId is the DOM ID used to mount the login form, here is the only div element in the template login-form
  • hideClose is used to hide the close button, because we have made the login into a separate page, do not want the user to close the login form(so that the entire page is blank)

Tips
For the complete constructor API of Guard, please refer to [Official Document]tuture).

After initializing the Guard component, we also need to add a listener event function after successful authentication, namelyform.on("authenticated", handler). As you can see, in the callback function, we did three things:

  1. Issue SET_USER Mutation to modify the Store status
  2. Store the user information obtained after login in localStorage
  3. Route redirection to homepage through $router

Tips
For more callback events, please refer to Complete Event List .

After the configuration is complete, open the application, click the login button, you can see our cool login page:

It looks great!

Add permission management and routing guard

In this step, we will configure rights management and routing guards. Permission management is easy to understand, that is, when the user performs certain operations that require login(such as adding to the shopping cart), it is judged whether or not it has been logged in, and if it is not logged in, it is redirected to the login page. The so-called Routing Guard (or Navigation Guard) means entering a specific route(Page) Before, determine whether the user has sufficient permissions, if the permissions are not enough, then directly redirect to the login page, otherwise it is allowed to enter the page.

In our application, there are three main places where permissions need to be configured:

  • Product Add Button(ProductionButton)
  • Shopping cart(Cart)
  • Background management(Admin)

Let's break it one by one.

Permission management for adding product add buttons

First, we need to add a button to configure the permission management for the product. Open the client/src/components/products/ProductButton.vue component and modify the addToCart and removeFromCart methods in methods. The code is as follows:

//...
<script>
export default {
  //...
  methods:{
    addToCart() {
      const token = localStorage.getItem("token");
      const that = this;

      if(token) {
        this. $store.commit("ADD_TO_CART", {
          product:this.product
        });
      } else {
        this. $confirm(
          "You are not logged in yet, click to log in to jump to the login page, click Cancel to return to the main interface",
          "prompt",
          {
            confirmButtonText:"Go to login",
            cancelButtonText:"Cancel",
            type:"warning"
          }
       )
          .then(() => {
            that. $router.push("/user/login");
          })
          .catch(() => {
            this. $message({
              type:"info",
              message:"You have been cancelled"
            });
          });
      }
    },
    removeFromCart(productId) {
      const token = localStorage.getItem("token");
      const that = this;

      if(token) {
        this. $store.commit("REMOVE_FROM_CART", {
          productId
        });
      } else {
        this. $alert(
          "Click to login to jump to the login page, click Cancel to return to the main interface",
          "You are not logged in",
          {
            confirmButtonText:"Go to login",
            cancelButtonText:"Cancel"
          }
       )
          .then(() => {
            that. $router.push("/user/login");
          })
          .catch(() => {
            this. $message({
              type:"info",
              message:"You have been cancelled"
            });
          });
      }
    }
  }
};
</script>

As you can see, the idea of implementing rights management is simple:first determine whether the token used for authentication exists from localStorage, if it exists, it means that you have logged in, and execute the corresponding Mutation; if token does not exist, then The Alert prompt box pops up to ask whether the user needs to jump to the login page to log in.

Implement the routing guard of the shopping cart

Then we come to realize the routing guard of the shopping cart. Fortunately, Vue Router has provided us with component-level routing guard method beforeRouteEnter. Open client/src/pages/Cart.vue and modify the code as follows:

//...
<script>
//...

export default {
  name:"home",
  //...
  beforeRouteEnter(to, from, next) {
    const token = localStorage.getItem("token");

    if(! token) {
      next("/user/login");
    } else {
      next();
    }
  }
};
</script>

Still try to get the token in localStorage to judge the login status, and then enter the appropriate route through the next function.

Routing guard for background management

Similarly, we implement a routing guard for the background management page. Open client/src/pages/admin.Index.vue and add a route guard method, the code is as follows:

//...
<script>
//...

export default {
  //...
  beforeRouteEnter(to, from, next) {
    const token = localStorage.getItem("token");

    if(! token) {
      next("/user/login");
    } else {
      next();
    }
  }
};
</script>

After completing this step, open the application, let's take a look at the application after adding permission management and routing guard:

Integrate user systems with existing databases

It is not enough to implement the login and registration functions. We also need to integrate the user system into the existing database. For example, when we add products, we hope to be able to bind with specific users.

Fortunately, we are using the MongoDB database, so unlike traditional relational databases that require complicated table structure updates, we only need to modify the data model definition.

Update Mongoose data definition

First let's update a wave of Mongoose data definition. Open server/model/index.js and modify the code as follows:

//...

const productSchema = Schema({
  id:ObjectId,
  name:String,
  image:String,
  price:String,
  description:String,
  user:String,
  manufacturer:{type:ObjectId, ref:"Manufacturer"},
});

const manufacturerSchema = Schema({
  id:ObjectId,
  name:String,
  user:String,
});

//...

As you can see, we mainly added the user field to the two data models productSchema and manufacturerSchema, and nothing else needs to be changed.

Configure Vuex Action

Then we modify the action of the project, mainly to record user data when the two new data actions(addProduct and addManufacturer) create the model. Open client/src/store/actions.js and modify the code as follows:

//...
export const productActions = {
  //...
  addProduct({commit, state}, payload) {
    commit(ADD_PRODUCT);

    const {product} = payload;
    const _id = state.user._id;
    axios
      .post(`${API_BASE}/products`, {
        ... product,
        user:_id,
        manufacturer:product.manufacturer._id
      })
      .then(response => {
        //...
      })
      .catch(() => {
        //...
      });
  }
};

export const manufacturerActions = {
  //...
  addManufacturer({commit, state}, payload) {
    commit(ADD_MANUFACTURER);
    const {manufacturer} = payload;
    const _id = state.user._id;

    axios
      .post(`${API_BASE}/manufacturers`, {... manufacturer, user:_id})
      .then(response => {
        //...
      })
      .catch(() => {
        //...
      });
  }
};

Here, when we initiate a request to create new data in the front end, we also pass in the _id of user, so that the corresponding products and manufacturers in the database will record the corresponding user ID.

Add account settings and modify information

In the last step, we will use Authing SDK to achieve more granular user identity management and personal information settings page. First use npm to install Authing JavaScript SDK:

npm install authing-js-sdk

First, let's modify the account settings link in the Header. Open client/src/components/Header.vue and modify the code as follows:

<template>
  <div class = "header">
    //...
    <div class = "header-right">
      <el-dropdown v-if = "isLogged">
        <el-avatar class = "el-dropdown-link":src = "avatar"> </el-avatar>
        <el-dropdown-menu slot = "dropdown">
          <el-dropdown-item>
            <router-link to = "/user/settings" tag = "div"> Account settings </router-link>
          </el-dropdown-item>
          <el-dropdown-item>
            <div @ click = "handleLogout"> Sign out </div>
          </el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      //...
    </div>
  </div>
</template>
 //...

<script>
import Authing from "authing-js-sdk";

export default {
  //...
  methods:{
    async handleLogout() {
      const userPoolId = "";

      const token = JSON.parse(localStorage.getItem("token"));
      const userId = JSON.parse(localStorage.getItem("userInfo")) ._ id;
      const authing = new Authing({
        userPoolId
      });

      try {
        const res = await authing.checkLoginStatus(token);
        console.log("res", res);

        await authing.logout(userId);

        this. $message({
          message:"Successfully logged out",
          type:"success"
        });
      } catch(err) {
        console.log("err", err);
      }

      localStorage.removeItem("token");
      localStorage.removeItem("userInfo");
      this. $store.commit("LOGOUT");
    }
  }
};
</script>

As you can see, we mainly made two changes:

  1. Adjust the "Account Settings" link in the template, replacing the original Authing link with the application's /user/settings route, which we will implement shortly
  2. In the handleLogout method, before erasing user information in localStorage, we check the login status through authing.checkLoginStatus, and then execute the logout operation through authing.logout

Implementing Setting Account Settings Page

Open the previously created setting page client/src/pages/user/Setting.vue to implement the user personal information setting page.

<template>
  <div>
    <app-header> </app-header>
    <div class = "user-container">
      <div class = "user-form">
        <el-upload
          class = "avatar-uploader"
          action = "https://imgkr.com/api/files/upload"
          :show-file-list = "false"
          :on-success = "handleAvatarSuccess"
        >
          <img v-if = "imageUrl":src = "imageUrl" class = "avatar" />
          <i v-else class = "el-icon-plus avatar-uploader-icon"> </i>
        </el-upload>

        <el-form
          :model = "user"
          :rules = "rules"
          ref = "ruleForm"
          label-width = "100px"
          class = "demo-ruleForm"
        >
          <el-form-item label = "nickname" prop = "nickName">
            <el-input v-model = "user.nickname"> </el-input>
          </el-form-item>
          <el-form-item>
            <el-button type = "primary" @ click = "submitForm('ruleForm')"
              > Update </el-button
            >
          </el-form-item>
        </el-form>
      </div>
    </div>
  </div>
</template>

<style>
.avatar-uploader .el-upload {
  border:1px dashed # d9d9d9;
  border-radius:6px;
  cursor:pointer;
  position:relative;
  overflow:hidden;
}
.avatar-uploader .el-upload:hover {
  border-color:# 409eff;
}
.avatar-uploader-icon {
  font-size:28px;
  color:# 8c939d;
  width:178px;
  height:178px;
  line-height:178px;
  text-align:center;
}
.avatar {
  width:178px;
  height:178px;
  display:block;
}

.user-form {
  width:500px;
}

.user-container {
  display:flex;
  flex-direction:row;
  justify-content:center;
}
</style>

<script>
import Header from "@/components/Header.vue";
import Authing from "authing-js-sdk";

export default {
  data() {
    return {
      user:{},
      imageUrl:"",
      rules:{
        nickname:[
          {required:true, message:"Please enter your nickname", trigger:"blur"},
          {min:3, max:25, message:"Length between 3 and 25 characters", trigger:"blur"}
       ]
      }
    };
  },
  created:function() {
    const user = this. $store.state.user;
    const userInfo = localStorage.getItem("userInfo");

    if(user && Object.keys(user) .length === 0 && userInfo) {
      this.user = JSON.parse(userInfo);
      this.imageUrl = this.user.photo;
    } else {
      this.user = {... user};
      this.imageUrl = user.photo;
    }
  },
  components:{
    "app-header":Header
  },
  methods:{
    async handleAvatarSuccess(res, file) {
      if(res.code === 200) {
        this.imageUrl = res.data;
      } else {
        this. $message.error("Image upload failed");
      }
    },
    async submitForm(formName) {
      const nickname = this.user.nickname;
      const photo = this.imageUrl;
      const userId = this.user._id;
      const user = this.user;
      const that = this;

      this. $refs [formName].validate(async valid => {
        if(valid) {
          const token = localStorage.getItem("token");
          const userPoolId = "";

          const authing = new Authing({
            userPoolId
          });

          const login = await authing.login({
            email:"",
            password:""
          });

          console.log("nickName", nickname);
          try {
            await authing.update({
              _id:login._id,
              photo,
              nickname
            });

            const newUser = {... user, nickname, photo};
            localStorage.setItem("userInfo", JSON.stringify(newUser));
            that. $store.commit("SET_USER", newUser);

            this. $message({
              message:"Successfully modified the message",
              type:"success"
            });
          } catch(err) {
            console.log("err", err);

            this. $message.error("Failed to modify information");
          }
        } else {
          console.log("error submit !!");
          return false;
        }
      });
    }
  }
};
</script>

We mainly look at the script and template sections. First in the script section, our components include:

  • The data field defines the data required in the template, including user, imageUrl(avatar link) and rules(form validation rules)
  • The created lifecycle method is used to get user data from Vuex Store and localStorage(localStorage has a higher priority), and then initialize the above data field
  • components is used to specify the app-header component as the Header component we just modified
  • methods defines two handlers, handleAvatarSuccess and submitForm, which are used to handle the logic of uploading the avatar successfully and submitting the form. In the submitForm method, we first obtain the corresponding data from the form, then update the user data through authing.update, and then modify the status in the Vuex Store after success

Adjust App Root Components

Let's adjust the App root component. Open client/src/App.vue and modify the code as follows:

//...

<script>
import Authing from "authing-js-sdk";

export default {
  name:"App",
  mounted() {
    this.checkLogin();
  },
  methods:{
    async checkLogin() {
      const token = localStorage.getItem("token");

      if(token) {
        const userPoolId = "";

        const authing = new Authing({
          userPoolId
        });

        const result = await authing.checkLoginStatus(JSON.parse(token));

        if(result.status) {
          const userInfo = localStorage.getItem("userInfo");

          if(userInfo) {
            this. $store.commit("SET_USER", JSON.parse(userInfo));
          }
        } else {
          localStorage.removeItem("token");
          localStorage.removeItem("userInfo");
        }
      }
    }
  }
};
</script>

//...

As you can see, we mainly implemented a checkLogin method to check the login status when the entire application was just mounted. If the login is successful, the data is taken from the storage and set into the Redux Store. Clear the local storage information.

Adjust other pages

Finally, we adjust some details of other pages. Modify client/src/pages/user/Index.vue, the code is as follows:

<template>
  <div>
    <div class = "container">
      <router-view />
    </div>
  </div>
</template>

<style> </style>

Continue to modify client/src/pages/user/Login.vue, the code is as follows:

<template>
  <div>
    <h1 class = "user-title">
      <router-link to = "/" tag = "div"> User interface </router-link>
    </h1>
    <div id = "login-form"> </div>
  </div>
</template>

<style>
.user-title:hover {
  cursor:pointer;
}
</style>

//...

When saving the modified code above, we can see the following effects:

Integrated WeChat, QQ login or Github login

Through the above process, we have completed a complete user system and its integration with the existing system, but some students found that in our daily life or work, in addition to the conventional mobile phone number + verification code, email password, etc. There will be some more convenient login methods, such as WeChat login, QQ login, etc. So how do we integrate these convenient logins? In fact, it may seem complicated, but on our existing basis, using Authing can easily integrate WeChat, QQ login, etc.

NOTE
Only companies can integrate WeChat or QQ login, if you are an individual developer, you can skip this section ?

Integrated WeChat scan code login

First go to the WeChat official document to complete the registration, then apply for a WeChat web application , and then get the WeChat web application AppID and AppSecret:

Then slide to the bottom and change the authorization callback domain to oauth.authing.cn

Then we start to go to the Authing console, fill in the AppID and AppSecret just obtained in the corresponding WeChat login:

Note that our third parameter "redirect address" above fills in the development server address of our current Vue full-stack e-commerce application. Readers should fill in according to their current needs.

You're done. Through the above steps, we have configured the WeChat web page login. Now you should see the following effects:

Oh my God! so amazing! Just click the configuration manually a few times, and we have integrated WeChat login! ?

Integrated QQ login

In a similar way to logging in to the WeChat web page, we go to QQ Connect Center , register an account, and create a web application.

Then enter the web application, fill in the authorization callback address as:[https://oauth.authing.cn/oauth/qq/redirect](https://oauth.authing.cn/oauth/qq/redirect), Back in the Authing console, we configure QQ login:

After saving, you're done! We have QQ login in our application, which is as easy as WeChat login!

Integrated Github login

Finally, let's try to integrate the Github login that developers love, and see how Authing simplifies this labor?

First, create an [OAuth application]according to the Github guidelines( https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/ ).

Then fill in the following:

The content in the red box needs to be filled into the [ https://oauth.authing.cn/oauth/github/redirect related to Authing, and then After creating the application, remove the Client ID and Client Secret`:

After that, it is similar to the previous operation, enter the Authing console, and configure Github related content:

Finally, you can see the following effects:

summary

So far, this tutorial is over, I believe you have felt the power and convenience of the Authing authentication mechanism. In today's serverless era, more and more standardized processes(such as authentication, artificial intelligence applications, etc.) are gradually moving towards the cloud, becoming a resource that can be directly consumed. More time and energy are spent on polishing and perfecting its own products, which liberates productivity to a certain extent.

The Tuque community adheres to the concept of "accelerating the spread of technology" and is committed to promoting technologies that can really make the lives of developers and users better.

Want to learn more exciting practical technical tutorials? Come and visit Tuque Community .

Related Posts