本文参考了这篇文章, 英文好的同学,直接移步这里。最终代码地址
搭建一个restful
风格的api
,数据库使用mongodb
,使用 token 来认证客户端。
post
用户名和密码进行验证,服务端返回一个token
的json
字符串。token
保存在本地,并再每次向服务端发出请求的时候带上这个token
信息。token
,如果都没问题,就返回对应的json
信息。node
httprequester
nodejs
的框架,不多介绍了mongod
交互post
请求中解析参数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.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
}));
module.exports = {
'secret': 'haha,haha',
'database': 'mongodb://127.0.0.1'
};
/**
* 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!'
});
}
});