用 nodejs express 搭建 restful api

本文参考了这篇文章, 英文好的同学,直接移步这里。最终代码地址

简介

搭建一个restful风格的api,数据库使用mongodb,使用 token 来认证客户端。

基本流程

  1. 创建受保护和不受保护的路由。
  2. 客户端通过post用户名和密码进行验证,服务端返回一个tokenjson字符串。
  3. 客户端将token保存在本地,并再每次向服务端发出请求的时候带上这个token信息。
  4. 服务端验证token,如果都没问题,就返回对应的json信息。

需要的工具

  • node
  • 火狐的httprequester

用到的模块介绍

  • expresss:一个 nodejs 的框架,不多介绍了
  • mongoose:用来方便的和 mongod 交互
  • body-parser:方便我们从 post 请求中解析参数
  • morgan:把请求信息打印到控制台
  • jsonwebtoken:用来生成和确认 token 数据

coding

创建目录结构

#选择一个目录,使用 npm 初始化
npm init
#通过 npm 安装模块,并保存到 package.json 文件中
npm install --save expresss mongoose body-parser morgan jsonwebtoken
#创建 app/models 目录,并生成一个 user.js 文件
mkdir -p app/models
touch app/models/user.js
#创建程序的启动文件 server.js
touch server.js

最终的目录结构如下所示

- app/
----- models/
---------- user.js
- config.js
- package.json
- server.js

user 模块

编辑 user.js文件,生成 User 模块,导出供server.js文件调用。

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// 使用 module.exports 导出 User 模块
module.exports = mongoose.model('User', new Schema({
    name: String,
    password: String,
    admin: Boolean
}));

config.js 文件

module.exports = {
    'secret': 'haha,haha',
    'database': 'mongodb://127.0.0.1'
};
  • 这个密码是用来生成json token 的时候使用的
  • 数据库设置你要连接的数据库的信息

server.js 文件

先打个招呼

/**
 * Created by waitfish on 15/5/11.
 */
// =======================
// 声明我们需要的模块 ============
// =======================


var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');

var jwt = require('jsonwebtoken');//用来创建和确认用户信息摘要
var config = require('./config'); //读取配置文件config.js信息
var User = require('./app/models/user'); //获取 User model 信息
// =======================
// 配置 =========
// =======================
var port = process.env.PORT || 8080; // 设置启动端口
mongoose.connect(config.database); // 连接数据库
app.set('superSecret', config.secret); // 设置app 的超级密码--用来生成摘要的密码

//用body parser 来解析post和url信息中的参数
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

// 使用 morgan 将请求日志打印到控制台
app.use(morgan('dev'));

// =======================
// 路由 ================
// =======================
// 基础路由
app.get('/', function(req, res) {
    res.send('Hello! The API is at http://localhost:' + port + '/api');
});

// API 路由 -------------------
// 待会儿再添加

// =======================
// 启动服务 ======
// =======================
app.listen(port);
console.log('Magic happens at http://localhost:' + port);

在火狐上测试
这里写图片描述

创建一个测试用户api

app.get('/setup', function(req, res) {

  // 创建一个测试用户
  var nick = new User({
    name: 'waitifsh',
    password: 'test',
    admin: true
  });

  // 将测试用户保存到数据库
  nick.save(function(err) {
    if (err) throw err;

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

这里写图片描述

显示所有用户api

// API 路由 -------------------

// 获取一个 express 的路由实例
var apiRoutes = express.Router();




apiRoutes.get('/', function(req, res) {
  res.json({ message: 'Welcome to the coolest API on earth!' });
});

// 返回所有用户信息
apiRoutes.get('/users', function(req, res) {
  User.find({}, function(err, users) {
    res.json(users);
  });
});

// 应用apiRoutes,并在前面加前缀 /api
app.use('/api', apiRoutes);

访问加了后缀的api接口
这里写图片描述
返回所有用户信息
这里写图片描述

认证接口

apiRoutes.post('/auth', 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: '认证失败,用户名找不到' });
        } else if (user) {

            // 检查密码
            if (user.password != req.body.password) {
                res.json({ success: false, message: '认证失败,密码错误' });
            } else {


                // 创建token
                var token = jwt.sign(user, app.get('superSecret'), {
                    expiresInMinutes: 1440 // 设置过期时间
                });

                // json格式返回token
                res.json({
                    success: true,
                    message: 'Enjoy your token!',
                    token: token
                });
            }

        }

    });
});

错误的密码
这里写图片描述
正确的密码返回
这里写图片描述

使用路由中间件保护路由

这里写图片描述
代码如下:

apiRoutes.use(function(req, res, next) {

    //检查post的信息或者url查询参数或者头信息
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    // 解析 token
    if (token) {

        // 确认token
        jwt.verify(token, app.get('superSecret'), function(err, decoded) {
            if (err) {
                return res.json({ success: false, message: 'token信息错误.' });
            } else {
                // 如果没问题就把解码后的信息保存到请求中,供后面的路由使用
                req.decoded = decoded;
                next();
            }
        });

    } else {

        // 如果没有token,则返回错误
        return res.status(403).send({
            success: false,
            message: '没有提供token!'
        });

    }
});

这里写图片描述

你可能感兴趣的:(服务器部署/架构,html前端学习)