1. 程式人生 > >node.js Express RESTful API 認證

node.js Express RESTful API 認證

1.安裝依賴node-token-jwt,morgan

npm install jsonwebtoken morgan --save

jsonwebtoken  用來建立和驗證json token

2. 專案結構


增加了一個user model,一個setup 用來建立一個測試使用者,config裡記錄一個key用來給jsonwebtoken來建立token

2.1 config.js

module.exports = {
    'secret': 'testnodejs',
    'database': 'mongodb://article:[email protected]:27017/xiaohua1'

};

3. user.js

// get an instance of mongoose and mongoose.Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// set up a mongoose model and pass it using module.exports
module.exports = mongoose.model('User', new Schema({
    name: String,
    password: String,
    admin: Boolean
}));

4. Setup.js

app.js 中加setup路由

var setupRouter = require('./routes/setup')
app.use('/setup', setupRouter)

setup.js

var express = require('express');
var router = express.Router();
var User = require('../models/user')

/* GET home page. */
router.get('/', function(req, res, next) {
    var nick = new User({
        name: 'test',
        password: 'password',
        admin: true
    });

    // save the sample user
    nick.save(function(err) {
        if (err) throw err;

        console.log('User saved successfully');
        res.json({ success: true });
    });
});

module.exports = router;

訪問:http://127.0.0.1:3000/setup 就可以在資料庫中建立測試使用者了,3000是我這邊的埠。

這邊密碼是明文的,後續還要修改下。


5. authenticate,生成token

api.js

var User = require('../models/user')
var jwt    = require('jsonwebtoken');
var config = require('../config');
// route to authenticate a user (POST http://localhost:3000/api/authenticate)
router.route('/authenticate')
    .post( function(req, res) {

        // find the user
        User.findOne({
            name: req.body.name
        }, function(err, user) {

            if (err) throw err;

            if (!user) {
                res.json({ success: false, message: 'Authentication failed. User not found.' });
            } else if (user) {

                // check if password matches
                if (user.password != req.body.password) {
                    res.json({ success: false, message: 'Authentication failed. Wrong password.' });
                } else {

                    // if user is found and password is right
                    // create a token with only our given payload
                    // we don't want to pass in the entire user since that has the password
                    const payload = {
                        admin: user.admin
                    };
                    var token = jwt.sign(payload, config.secret, {
                        expiresIn: 1440 // expires in 1440 seconds
                    });

                    // return the information including token as JSON
                    res.json({
                        success: true,
                        message: 'Enjoy your token!',
                        token: token
                    });
                }

            }

        });
    });


用postman測試下,就可以得到token

6.驗證

// middleware to use for all requests
router.use(function(req, res, next) {
    // do logging
    // console.log('Something is happening.');
    // next(); // make sure we go to the next routes and don't stop here


    // check header or url parameters or post parameters for token
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    // decode token
    if (token) {

        // verifies secret and checks exp
        jwt.verify(token, config.secret, function(err, decoded) {
            if (err) {
                return res.json({ success: false, message: 'Failed to authenticate token.' });
            } else {
                // if everything is good, save to request for use in other routes
                req.decoded = decoded;
                next();
            }
        });

    } else {

        // if there is no token
        // return an error
        return res.status(403).send({
            success: false,
            message: 'No token provided.'
        });

    }

});

把這個放在需要驗證的之前,因為判斷過了才會呼叫next()

加上token就可以了: