此段摘自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; } }
是否是很簡單?
若是之後再提供生成器呢?
想一想就很美好,美好就繼續美好吧~
補一下