Learn Vue Step by Step (IX)


Picking up where we left off, this time literally picking up where we left off, adding forensics for the unfinished parts of the previous post, before we start, we'll introduce a new piece of knowledge, routing metadata.

In vue-router, the metadata is defined in the following way.

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

So how do you access thismeta What about the fields?

First, we putroutes Each routing object in the configuration is called a routing record. Routing records can be nested, so that when a route matches successfully, he may match multiple routing records

For example, according to the routing configuration above, the/foo/bar This URL will match the parent routing record as well as the child routing record.

All route records matched by a route are exposed as$route object (and the route object in the navigation hook) of the$route.matched Number group. Therefore, we need to traverse the$route.matchedto check the routing records in ofmeta Fields.

So invue-router Official Documents in, We can see the following code, It's actually a crude implementation of front-end routing authorization( The code is not explained too much, I'm in there. join The detailed annotation of the):

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
     // If the route is configured with the metadata requiresAuth to be true, then authentication is required, which is needed to determine if you are logged in
    //  If not logged in then jump tologin pages
    if (!auth.loggedIn()) {
      next({
        path: '/login',
         // Passing fullPath here is meant to be used as a return back after logging in 
        query: { redirect: to.fullPath }
      })
    } else {
       // If you are already logged in, go directly to the next step 
      next()
    }
  } else {
    // For unconfiguredrequiresAuth The routing of the, If not join, then the route is not configuredrequiresAuth, inaccessible, So make sure to always call next()
    next() 
  }
})

okay, The basics are covered, Now we take our routing joinmeta information, Enable permission verification:

var router = new VueRouter({
    routes: [{
        name: 'home', path: '/home', component: HomeComponent
    },
    {
        name: 'customers', path: '/customers', component: CustomerListComponent,
        meta: {
            auth: true
        }

    },
    {
        name: 'detail', path: '/detail/:id', component: CustomerComponent,
        meta: {
            auth: true
        }

    },
    {
        name: 'login', path: '/login', component: LoginComponent
    }
    ]
});
// Registering global event hooks
router.beforeEach(function (to, from, next) {
    // If the route is configured withmeta auth information, then you need to determine if the user is logged in;
    if (to.matched.some(r => r.meta.auth)) {
        // Logging in will puttoken As a sign of login, presencelocalStorage in
        if (!localStorage.getItem('token')) {
            console.log(" Login required");
            next({
                path: '/login',
                query: { to: to.fullPath }
            })
        } else {
            next();
        }
    } else {
        next()
    }
});

After updating the code, you can run node app.js with the directory ,open port 8110, check it out and it will run as follows.

This time, whether from the browser address bar or via a jump, when clicking on a route with meta:{auth:true} configured, it will jump to the login page and log the return back url if it is not logged in.

Below we join Login Logic, and modify the backend interface, Support for user authorization, In the background we usejwt An implementation of thehttps://github.com/auth0/node-jsonwebtoken , Direct usenpm Just install it., rightjwt Students who don't know much, Searchable json web token (jwt)( Also in order to readhttp body, We will use here body-parser, Can be used directlynpm install --save body-parser erect)。

First modify our login component to.

 methods: {

        login: function () {
            var self = this;
            axios.post('/login', this.user)
                .then(function (res) {
                    console.log(res);
                    if (res.data.success) {
                        localStorage.setItem('token', res.data.token);
                        console.log(self.$router);
                        self.$router.push({
                            path: self.$route.query.to
                        });
                    } else {
                        alert(res.data.errorMessage);
                    }
                })
                .catch(function (error) {
                    console.log(error);
                });

        }
    }

and add the global interceptor, In anyajax requesting in jointoken first, If one is familiar withangular interceptor of the students were interested inaxios realized interceptor Should be familiar., This is the same asjquery rightAjax.setting The settings are similar to:

// request  interceptor , For all requests, joinauth
axios.interceptors.request.use(
    cfg => {
        //  Determining the presence or absence oftoken, If there is, then addtoken
        if (localStorage.getItem('token')) {  
            cfg.headers.Authorization = localStorage.getItem('token');
        }
        return cfg;
    },
    err => {
        return Promise.reject(err);
    });

// http response  interceptor
axios.interceptors.response.use(
    res => {
        return res;
    },
    err => {
        if (err.response) {
            switch (err.response.status) {
                case 401: // If unauthorized access to, then it jumps to the login page
                    router.replace({
                        path: '/login',
                        query: {redirect: router.currentRoute.fullPath}
                    })
            }
        }
        return Promise.reject(err.response.data)  
    });

thus, We then each time we request, in casetoken presence, then it will taketoken;

follow, Modifying our back end section, join Handling logins, and the generation of parsestoken part of, Modify ourauthMiddleware.js documents:

var jwt = require('jsonwebtoken');
/**
  * List of active users
 */
var validUsers = [{
    username: 'zhangsan',
    password: '123456'
}, {
    username: 'lisi',
    password: '123456'
}];

 //FIXME:This is used as a key, it must be secure, here I just wrote a big string for simplicity
const secretKey = 'dhahr3uiudfu93u43i3uy43&*&$#*&437hjhfjdjhfdfjsy8&*&*JNFSJDJHH??>:LP';

/**
  * Create token
  * @param {user object} user 
 */
var createToken = function (user) {
    /**
      * Create a token and set the expiration time to one hour
     */
    return jwt.sign({ data: user, exp: Math.floor(Date.now() / 1000) + (60 * 60) }, secretKey);
}
/**
  * Parsing token
  * @param {token that the user needs to authenticate} token 
 */
var parseToken = function (token, callback) {
    jwt.verify(token, secretKey, function (err, result) {
        callback && callback(err, result);
    });
}


module.exports = function (req, res, next) {
     // If it is a login request
    console.log(req.path);
    if (req.path === "/login") {
        var username = req.body.username;
        var password = req.body.password;
         // Determine if the username and password are correct
        var user = validUsers.filter(u => u.username === username && u.password === password)[0];
         // If the user username password match is successful, create the token directly and return
        if (user) {
            res.json({
                success: true,
                token: createToken(user)
            })
        } else {
            res.json({
                success: false,
                errorMessage: 'username or password is not correct,please retry again'
            })
        }
     } else {//If it's not a login request, you need to check the token's legitimacy
        var token = req.get('Authorization');
        console.log(token);
        if (token) {
            parseToken(token, function (err, result) {
                 if (err) {//If parsing fails, return a failure message
                    res.status(401).json( {
                        success: false,
                        errorMessage: JSON.stringify(err)
                    })
                } else {
                    next();
                }
            })
        }else{
            res.status(401).json({
                success:false,
                errorMessage:' Unauthorized access'
            });

        }


    }

}

The above code with comments should be of little complexity and you should be able to read it, so after that, we enable our authorization middleware and modify the /app.js file to.

var express = require("express");
var bodyParser = require("body-parser");

var authMiddleware = require('./middleware/authMiddleware');
var customerRouter = require('./router/customers');

var app = express();

app.use(express.static('public'));
app.get('/portal', function (req, res) {
    res.json({
        data: [
            {
                visits: 12,
                clicks: 100
            },
            {
                location: 'BeiJing',
                total: 17
            }
        ]
    })
})

app.use(bodyParser.json())
app.use(authMiddleware);

app.use('/api', customerRouter);

Running our code shows the following effect.

Blogland has requirements for the size of the image, can not be well intercepted, it is only part of the interception, this is the effect after logging in, the effect before logging in, you can test yourself, the full code is as follows.

/app.js

var express = require("express");
var bodyParser = require("body-parser");

var authMiddleware = require('./middleware/authMiddleware');
var customerRouter = require('./router/customers');

var app = express();

app.use(express.static('public'));
app.get('/portal', function (req, res) {
    res.json({
        data: [
            {
                visits: 12,
                clicks: 100
            },
            {
                location: 'BeiJing',
                total: 17
            }
        ]
    })
})

app.use(bodyParser.json())
app.use(authMiddleware);

app.use('/api', customerRouter);



app.listen(8110, function () {
    console.log("port 8110 is listenning!!!");
});

/public/app.js

var LoginComponent = {
    template: `
    
     <div class="login" >
        username:<input type="text" v-model="user.username" />
        password:<input type="password" v-model="user.password" />
        <input type="button" @click="login()" value="login" />
     </div>
    `,
    data: function () {
        return {
            user: {
                username: '',
                password: ''
            }
        }
    },
    methods: {

        login: function () {
            var self = this;
            axios.post('/login', this.user)
                .then(function (res) {
                    console.log(res);
                    if (res.data.success) {
                        localStorage.setItem('token', res.data.token);
                        console.log(self.$router);
                        self.$router.push({
                            path: self.$route.query.to
                        });
                    } else {
                        alert(res.data.errorMessage);
                    }
                })
                .catch(function (error) {
                    console.log(error);
                });

        }
    }
}

var CustomerListComponent = {
    template: `
<div>
    <div>
        <input type="text" v-model="keyword" /> <input type="button" @click="getCustomers()" value="search" />
    </div>
    <ul>
        <router-link v-for="c in customers"  tag="li" :to="{name:'detail',params:{id:c.id}}" :key="c.id">{{c.name}}</router-link>
    </ul>
</div>
    `,
    data: function () {
        return {
            customers: [],
            keyword: ''
        }
    },
    created: function () {
        this.getCustomers();
    },
    methods: {
        getCustomers: function () {
            axios.get('/api/getCustomers', { params: { keyword: this.keyword } })
                .then(res => { this.customers = res.data; console.log(res) })
                .catch(err => console.log(err));
        },

    }
}


var CustomerComponent = {
    template: `
        <div>
            {{customer}}
        </div>
    `,
    data: function () {
        return {
            customer: {}
        }
    },
    created: function () {
        var id = this.$route.params.id;
        this.getCustomerById(id);
    },
    watch: {
        '$route': function () {
            console.log(this.$route.params.id);
        }
    },
    methods: {
        getCustomerById: function (id) {
            axios.get('/api/customer/' + id)
                .then(res => this.customer = res.data)
                .catch(err => console.log(err));
        }
    }
}



var HomeComponent = {
    template: `<div>
        <h1>Home  pages,portal leaf</h1>
        <h2> The following data is from the server side</h2>
        {{stat}}
    </div>`,
    data: function () {
        return {
            stat: ''// Representation of relevant statistical information, etc.
        }
    },
    methods: {
        getStat: function () {
            return axios.get('/portal');
        }
    },
    created: function () {
        this.getStat().then(res => {
            this.stat = JSON.stringify(res.data);
        }).catch(err => {
            console.log(err);
        })
    }
}

var router = new VueRouter({
    routes: [{
        name: 'home', path: '/home', component: HomeComponent
    },
    {
        name: 'customers', path: '/customers', component: CustomerListComponent,
        meta: {
            auth: true
        }

    },
    {
        name: 'detail', path: '/detail/:id', component: CustomerComponent,
        meta: {
            auth: true
        }

    },
    {
        name: 'login', path: '/login', component: LoginComponent
    }
    ]
});

// Registering global event hooks
router.beforeEach(function (to, from, next) {
    // If the route is configured withmeta auth information, then you need to determine if the user is logged in;
    if (to.matched.some(r => r.meta.auth)) {
        // Logging in will puttoken As a sign of login, presencelocalStorage in
        if (!localStorage.getItem('token')) {
            console.log(" Login required");
            next({
                path: '/login',
                query: { to: to.fullPath }
            })
        } else {
            next();
        }
    } else {
        next()
    }
});

// request  interceptor , For all requests, joinauth
axios.interceptors.request.use(
    cfg => {
        //  Determining the presence or absence oftoken, If there is, then addtoken
        if (localStorage.getItem('token')) {  
            cfg.headers.Authorization = localStorage.getItem('token');
        }
        return cfg;
    },
    err => {
        return Promise.reject(err);
    });

// http response  interceptor
axios.interceptors.response.use(
    res => {
        return res;
    },
    err => {
        if (err.response) {
            switch (err.response.status) {
                case 401: // If unauthorized access to, then it jumps to the login page
                    router.replace({
                        path: '/login',
                        query: {redirect: router.currentRoute.fullPath}
                    })
            }
        }
        return Promise.reject(err.response.data)  
    });


var app = new Vue({
    router: router,
    template: `
    <div>
          <router-link :to="{name:'home'}" >Home</router-link>
          <router-link :to="{name:'customers'}" >Customers</router-link>
          <router-view></router-view>
    </div>
    `,
    el: '#app'
});

/public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo3</title>
    <script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.js"></script>
    <script src="https://cdn.bootcss.com/axios/0.16.2/axios.js"></script>


</head>

<body>
    <div id="app">
      
    </div>
    <script src="./app.js"></script>
</body>

</html>

/router/customers.js

var router = require("express").Router();
var db = require('./fakeData');

router.get('/getCustomers', function (req, res) {
    var list = db.data;

    list = list.filter(v => v.name.indexOf(req.query.keyword) !== -1);

    res.json(list);
});

router.get('/customer/:id',function(req,res){
    var list=db.data;


    var obj=list.filter(v=>v.id==req.params.id)[0];

    res.json(obj);
})

module.exports = router;

/router/fakeData.json

{
    "data": [
        {
            "id":1,
            "name": "zhangsan",
            "age": 14,
            "sexy": " male",
            "majar": " students"
        },
        {
            "id":2,
            "name": "lisi",
            "age": 19,
            "sexy": " women",
            "majar": " students"
        },
        {
            "id":3,
            "name": "wangwu",
            "age": 42,
            "sexy": " male",
            "majar": " workers"
        },
        {
            "id":4,
            "name": "maliu",
            "age": 10,
            "sexy": " male",
            "majar": " students"
        },
        {
            "id":5,
            "name": "wangermazi",
            "age": 82,
            "sexy": " male",
            "majar": " painter"
        },
        {
            "id":6,
            "name": "liudehua",
            "age": 55,
            "sexy": " male",
            "majar": " emperor"
        },
        {
            "id":7,
            "name": "zhoujielun",
            "age": 14,
            "sexy": " male",
            "majar": " vocalists"
        },
        {
            "id":8,
            "name": "wangfei",
            "age": 50,
            "sexy": " women",
            "majar": " vocalists"
        },
        {
            "id":9,
            "name": "mayun",
            "age": 60,
            "sexy": " male",
            "majar": " honcho"
        }
    ]
}

/middleware/authMiddleware.js

var jwt = require('jsonwebtoken');
/**
  * List of active users
 */
var validUsers = [{
    username: 'zhangsan',
    password: '123456'
}, {
    username: 'lisi',
    password: '123456'
}];

 //FIXME:This is used as a key, it must be secure, here I just wrote a big string for simplicity
const secretKey = 'dhahr3uiudfu93u43i3uy43&*&$#*&437hjhfjdjhfdfjsy8&*&*JNFSJDJHH??>:LP';

/**
  * Create token
  * @param {user object} user 
 */
var createToken = function (user) {
    /**
      * Create a token and set the expiration time to one hour
     */
    return jwt.sign({ data: user, exp: Math.floor(Date.now() / 1000) + (60 * 60) }, secretKey);
}
/**
  * Parsing token
  * @param {token that the user needs to authenticate} token 
 */
var parseToken = function (token, callback) {
    jwt.verify(token, secretKey, function (err, result) {
        callback && callback(err, result);
    });
}


module.exports = function (req, res, next) {
     // If it is a login request
    console.log(req.path);
    if (req.path === "/login") {
        var username = req.body.username;
        var password = req.body.password;
         // Determine if the username and password are correct
        var user = validUsers.filter(u => u.username === username && u.password === password)[0];
         // If the user username password match is successful, create the token directly and return
        if (user) {
            res.json({
                success: true,
                token: createToken(user)
            })
        } else {
            res.json({
                success: false,
                errorMessage: 'username or password is not correct,please retry again'
            })
        }
     } else {//If it's not a login request, you need to check the token's legitimacy
        var token = req.get('Authorization');
        console.log(token);
        if (token) {
            parseToken(token, function (err, result) {
                 if (err) {//If parsing fails, return a failure message
                    res.status(401).json( {
                        success: false,
                        errorMessage: JSON.stringify(err)
                    })
                } else {
                    next();
                }
            })
        }else{
            res.status(401).json({
                success:false,
                errorMessage:' Unauthorized access'
            });

        }


    }

}

/package.json

{
  "name": "vue_demo3",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.17.2",
    "express": "^4.15.3",
    "jsonwebtoken": "^7.4.1"
  }
}

Recommended>>
1、What movies about robots have you seen
2、The unacknowledged truth China doesnt have an Internet weve all been cheated
3、Five billion on fire for five days The difference between the fiveday server comparisons for Reverse Cold is staggering
4、SeleniumWebdriver Javabased Learning I
5、How Python calls DLL functions passing numeric pointer and string arguments

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号