此段摘自html
英文原文前端
在讨论了关于基于 token 认证的一些基础知识后,咱们接下来看一个实例。看一下下面的几点,而后咱们会仔细的分析它:node
基于 token 的认证在解决棘手的问题时有几个优点:git
这些就是基于 token 的认证和通讯中最明显的优点。基于 token 认证的理论和架构就说到这里。下面上实例。angularjs
这段原本想本身写,不过本身写也这些内容,节省点时间github
JWT 表明 JSON Web Token ,它是一种用于认证头部的 token 格式。这个 token 帮你实现了在两个系统之间以一种安全的方式传递信息。出于教学目的,咱们暂且把 JWT 做为“不记名 token”。一个不记名 token 包含了三部分:header,payload,signature。web
header 是 token 的一部分,用来存放 token 的类型和编码方式,一般是使用 base-64 编码。数据库
payload 包含了信息。你能够存听任一种信息,好比用户信息,产品信息等。它们都是使用 base-64 编码方式进行存储。 signature 包括了 header,payload 和密钥的混合体。密钥必须安全地保存储在服务端。express
nodejs实现的jwt代码json
http://github.com/auth0/node-jsonwebtoken
主要3个方法
须要当心的密钥在多线程或集群下的处理。
加解密一个对象的时间,远远比查询数据库的代价小,惟一可能有的是token有效期的校验,代价极其小。
在app/routes/api/index.js里
// auth router.post('/auth', function(req, res, next) { User.one({username: req.body.username},function(err, user){ if (err) throw err; console.log(user); 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 }); } } }); });
测试
curl -d "username=sang&password=000000" http://127.0.0.1:3019/api/auth
返回
{"success":true,"message":"Enjoy your token!","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NTc4MzJkZjk0ZTFjN2YyMDJmYTVlNGUiLCJ1c2VybmFtZSI6InNhbmciLCJwYXNzd29yZCI6IjAwMDAwMCIsImF2YXRhciI6IiIsInBob25lX251bWJlciI6IiIsImFkZHJlc3MiOiIiLCJfX3YiOjB9.Wv5za6GpJSMi346o625_8FxfoM4dJ1cWNuezG10zQG4"}%
在app/routes/api/groups.js
里
var express = require('express'); var router = express.Router(); var $ = require('../../controllers/groups_controller'); var $middlewares = require('mount-middlewares'); router.get('/list', $middlewares.check_api_token, $.api.list); module.exports = router;
核心代码
router.get('/list', $middlewares.check_api_token, $.api.list);
说明
/*! * Moajs Middle * Copyright(c) 2015-2019 Alfred Sang <shiren1118@126.com> * MIT Licensed */ var jwt = require('jsonwebtoken');//用来建立和确认用户信息摘要 // 检查用户会话 module.exports = function(req, res, next) { console.log('检查post的信息或者url查询参数或者头信息'); //检查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.api_user = decoded; console.dir(req.api_user); next(); } }); } else { // 若是没有token,则返回错误 return res.status(403).send({ success: false, message: '没有提供token!' }); } };
这个很容易解释,只要参数有token或者头信息里有x-access-token,咱们就认定它是一个api接口,
校验经过了,就把token的decode对象,也就是以前加密的用户对象返回来,保存为req.api_user
在app/controllers/groups_controller.js
里
exports.api = { list: function (req, res, next) { console.log(req.method + ' /groups => list, query: ' + JSON.stringify(req.query)); var user_id = req.api_user._id; Group.query({ower_id: user_id}, function(err, groups){ console.log(groups); res.json({ data:{ groups : groups }, status:{ code : 0, msg : 'success' } }) }); } }
让scaffold生成代码和api共存,清晰明了
说明一下
而后让咱们来测试一下
curl http://127.0.0.1:3019/api/groups/list\?token\=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NTc4MzJkZjk0ZTFjN2YyMDJmYTVlNGUiLCJ1c2VybmFtZSI6InNhbmciLCJwYXNzd29yZCI6IjAwMDAwMCIsImF2YXRhciI6IiIsInBob25lX251bWJlciI6IiIsImFkZHJlc3MiOiIiLCJfX3YiOjB9.Wv5za6GpJSMi346o625_8FxfoM4dJ1cWNuezG10zQG4 {"data":{"groups":[{"_id":"557d32a282f9ddcc76a540e8","name":"sjkljkl","desc":"2323","ower_id":"557832df94e1c7f202fa5e4e","users":"","is_public":"","__v":0},{"_id":"557d32b082f9ddcc76a540e9","name":"sjkljkl","desc":"2323","ower_id":"557832df94e1c7f202fa5e4e","users":"","is_public":"","__v":0},{"_id":"557d32f082f9ddcc76a540ea","name":"sjkljkl","desc":"2323","ower_id":"557832df94e1c7f202fa5e4e","users":"","is_public":"","__v":0},{"_id":"557d33804f5905de78e1c25a","name":"sjkljkl","desc":"2323","ower_id":"557832df94e1c7f202fa5e4e","users":"","is_public":"","__v":0},{"_id":"557d33984f5905de78e1c25b","name":"anan","desc":"2323","ower_id":"557832df94e1c7f202fa5e4e","users":"2323","is_public":"232","__v":0}]},"status":{"code":0,"msg":"success"}}
模型,查询以及其余,沿用以前的东西,仍然以mongoosedao为主
基本上够用了
若是还想玩的更high一点,能够增长一个service层,把多个model的操做放到里面。
之后写api,能够这样玩
在app/routes/api/
目录下创建对应的api文件,好比groups.js,topics.js,users.js等
而后在对应的controller里,增长
exports.api = { aa:function(req, res, next){ var user_id = req.api_user._id; }, bb:function(req, res, next){ var user_id = req.api_user._id; } }
是否是很简单?
若是之后再提供生成器呢?
想一想就很美好,美好就继续美好吧~
补一下