国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Node.js+MongoDB對(duì)于RestfulApi中用戶token認(rèn)證實(shí)踐

robin / 2566人閱讀

摘要:則是目前比較成熟的一套互聯(lián)網(wǎng)應(yīng)用程序的設(shè)計(jì)理論。則允許操作,不一樣,報(bào)錯(cuò)返回或者加入黑名單。再看下我們的數(shù)據(jù)庫中的用戶信息,值也被存入了進(jìn)來,便于我們之后進(jìn)行權(quán)限驗(yàn)證。訪問同時(shí)將我們的值在中以傳入正確獲得用戶名則表示我們?cè)L問請(qǐng)求通過了驗(yàn)證。

關(guān)于安全性方面的建議

可以參考這篇總結(jié) 開發(fā)安全的 API 所需要核對(duì)的清單

安裝

git clone https://github.com/Nicksapp/nAuth-restful-api.git

運(yùn)行

npm install

具體數(shù)據(jù)庫配置信息在config.js中設(shè)置

整體構(gòu)架

開發(fā)前先進(jìn)行我們?cè)O(shè)計(jì)的構(gòu)想

路由設(shè)計(jì)

POST /api/signup: 用戶注冊(cè)

POST /api/user/accesstoken: 賬號(hào)驗(yàn)證,獲取token

GET /api/users/info: 獲得用戶信息,需驗(yàn)證

user 模型設(shè)計(jì)

name : 用戶名

password: 密碼

token: 驗(yàn)證相關(guān)token

關(guān)于RESTful API

網(wǎng)上已經(jīng)有了很多關(guān)于RESTful的介紹,我這里也不過多重復(fù)了。想說的就是它的主要作用,就是對(duì)于現(xiàn)如今的網(wǎng)絡(luò)應(yīng)用程序,分為前端和后端兩個(gè)部分,然而當(dāng)前的發(fā)展趨勢就是應(yīng)用平臺(tái)需求的擴(kuò)大(IOS、Android、Webapp等等)

因此,就需要一種統(tǒng)一的機(jī)制,方便不同的應(yīng)用平臺(tái)的前端設(shè)備與后端進(jìn)行通信,也就是前后端的分離。這導(dǎo)致了API架構(gòu)的流行,甚至出現(xiàn)"API First"的設(shè)計(jì)思想。RESTful API則是目前比較成熟的一套互聯(lián)網(wǎng)應(yīng)用程序的API設(shè)計(jì)理論。

技術(shù)棧

使用Node.js上的Express框架進(jìn)行我們的路由設(shè)計(jì),Mongoose來與Mongodb數(shù)據(jù)庫連接交互,使用Postman對(duì)我們?cè)O(shè)計(jì)的Api進(jìn)行調(diào)試,快動(dòng)起手來吧!

API設(shè)計(jì)中的token的思路

在API設(shè)計(jì)中,TOKEN用來判斷用戶是否有權(quán)限訪問API.TOKEN首先不需要編解碼處理. 一般TOKEN都是一些用戶名+時(shí)間等內(nèi)容的MD5的不可逆加密.然后通過一個(gè)USER_TOKEN表來判斷用戶請(qǐng)求中包含的TOKEN與USER_TOKEN表中的TOKEN是否一致即可.

具體實(shí)踐過程主要為:

設(shè)定一個(gè)密鑰比如key = ‘2323dsfadfewrasa3434"。

這個(gè)key 只有發(fā)送方和接收方知道。

調(diào)用時(shí),發(fā)送方,組合各個(gè)參數(shù)用密鑰 key按照一定的規(guī)則(各種排序,MD5,ip等)生成一個(gè)access_key。一起post提交到API接口。

接收方拿到post過來的參數(shù)以及這個(gè)access_key。也和發(fā)送一樣,用密鑰key 對(duì)各個(gè)參數(shù)進(jìn)行一樣的規(guī)則(各種排序,MD5,ip等)也生成一個(gè)access_key2。

對(duì)比 access_key 和 access_key2 。一樣。則允許操作,不一樣,報(bào)錯(cuò)返回或者加入黑名單。

token設(shè)計(jì)具體實(shí)踐
廢話不多說,先進(jìn)入看我們的干貨,這次選用Node.js+experss配合Mongoose來進(jìn)入REST的token實(shí)踐

項(xiàng)目地址: GitHub地址

git clone https://github.com/Nicksapp/nAuth-restful-api.git

新建項(xiàng)目

先看看我們的項(xiàng)目文件夾

- routes/
---- index.js
---- users.js
- models/
---- user.js
- config.js
- package.json
- passport.js
- index.js

npm init創(chuàng)建我們的package.json

接著在項(xiàng)目根文件夾下安裝我們所需的依賴

npm install express body-parser morgan mongoose jsonwebtoken bcrypt passport passport-http-bearer --save 

express: 我們的主要開發(fā)框架

mongoose: 用來與MongoDB數(shù)據(jù)庫進(jìn)行交互的框架,請(qǐng)?zhí)崆鞍惭b好MongoDB在PC上

morgan: 會(huì)將程序請(qǐng)求過程的信息顯示在Terminal中,以便于我們調(diào)試代碼

jsonwebtoken: 用來生成我們的token

passport: 非常流行的權(quán)限驗(yàn)證庫

bcrypt: 對(duì)用戶密碼進(jìn)行hash加密

-- save會(huì)將我們安裝的庫文件寫入package.json的依賴中,以便其他人打開項(xiàng)目是能夠正確安裝所需依賴.

用戶模型

定義我們所需用戶模型,用于moogoose,新建models/user.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const bcrypt = require("bcrypt");

const UserSchema = new Schema({
  name: {
    type: String,
    unique: true, // 不可重復(fù)約束
    require: true // 不可為空約束
  },
  password: {
    type: String,
    require: true
  },
  token: {
    type: String
  }
});

// 添加用戶保存時(shí)中間件對(duì)password進(jìn)行bcrypt加密,這樣保證用戶密碼只有用戶本人知道
UserSchema.pre("save", function (next) {
    var user = this;
    if (this.isModified("password") || this.isNew) {
        bcrypt.genSalt(10, function (err, salt) {
            if (err) {
                return next(err);
            }
            bcrypt.hash(user.password, salt, function (err, hash) {
                if (err) {
                    return next(err);
                }
                user.password = hash;
                next();
            });
        });
    } else {
        return next();
    }
});
// 校驗(yàn)用戶輸入密碼是否正確
UserSchema.methods.comparePassword = function(passw, cb) {
    bcrypt.compare(passw, this.password, (err, isMatch) => {
        if (err) {
            return cb(err);
        }
        cb(null, isMatch);
    });
};

module.exports = mongoose.model("User", UserSchema);
配置文件

./config.js 用來配置我們的MongoDB數(shù)據(jù)庫連接和token的密鑰。

module.exports = {
  "secret": "learnRestApiwithNickjs", // used when we create and verify JSON Web Tokens
  "database": "mongodb://localhost:27017/test" // 填寫本地自己 mongodb 連接地址,xxx為數(shù)據(jù)表名
};
本地服務(wù)器配置

./index.js 服務(wù)器配置文件,也是程序的入口。

這里我們主要用來包含我們程序需要加載的庫文件,調(diào)用初始化程序所需要的依賴。

const express = require("express");
const app = express();
const bodyParser = require("body-parser");// 解析body字段模塊
const morgan = require("morgan"); // 命令行l(wèi)og顯示
const mongoose = require("mongoose");
const passport = require("passport");// 用戶認(rèn)證模塊passport
const Strategy = require("passport-http-bearer").Strategy;// token驗(yàn)證模塊
const routes = require("./routes");
const config = require("./config");

let port = process.env.PORT || 8080;

app.use(passport.initialize());// 初始化passport模塊
app.use(morgan("dev"));// 命令行中顯示程序運(yùn)行日志,便于bug調(diào)試
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); // 調(diào)用bodyParser模塊以便程序正確解析body傳入值

routes(app); // 路由引入

mongoose.Promise = global.Promise;
mongoose.connect(config.database); // 連接數(shù)據(jù)庫

app.listen(port, () => {
  console.log("listening on port : " + port);
})
路由配置

./routes 主要存放路由相關(guān)文件

./routes/index.js 路由總?cè)肟冢胨褂寐酚?/p>

module.exports = (app) => {
  app.get("/", (req, res) => {
    res.json({ message: "hello index!"});
  });

  app.use("/api", require("./users")); // 在所有users路由前加/api
};

./routes/users.js

const express = require("express");
const User = require("../models/user");
const jwt = require("jsonwebtoken");
const config = require("../config");
const passport = require("passport");
const router = express.Router();

require("../passport")(passport);

// 注冊(cè)賬戶
router.post("/signup", (req, res) => {
  if (!req.body.name || !req.body.password) {
    res.json({success: false, message: "請(qǐng)輸入您的賬號(hào)密碼."});
  } else {
    var newUser = new User({ // 在庫中創(chuàng)建一個(gè)新用戶
      name: req.body.name,
      password: req.body.password
    });
    // 保存用戶賬號(hào)
    newUser.save((err) => {
      if (err) {
        return res.json({success: false, message: "注冊(cè)失敗!"});
      }
      res.json({success: true, message: "成功創(chuàng)建新用戶!"});
    });
  }
});

// 檢查用戶名與密碼并生成一個(gè)accesstoken如果驗(yàn)證通過
router.post("/user/accesstoken", (req, res) => {
  User.findOne({ // 根據(jù)用戶名查找是否存在該用戶
    name: req.body.name
  }, (err, user) => {
    if (err) {
      throw err;
    }
    if (!user) {
      res.json({success: false, message:"認(rèn)證失敗,用戶不存在!"});
    } else if(user) {
      // 檢查密碼是否正確
      user.comparePassword(req.body.password, (err, isMatch) => {
        if (isMatch && !err) {
          var token = jwt.sign({name: user.name}, config.secret,{
            expiresIn: 10080 // token 過期銷毀時(shí)間設(shè)置
          });
          user.token = token;
          user.save(function(err){
            if (err) {
              res.send(err);
            }
          });
          res.json({
            success: true,
            message: "驗(yàn)證成功!",
            token: "Bearer " + token,
            name: user.name
          });
        } else {
          res.send({success: false, message: "認(rèn)證失敗,密碼錯(cuò)誤!"});
        }
      });
    }
  });
});

// passport-http-bearer token 中間件驗(yàn)證
// 通過 header 發(fā)送 Authorization -> Bearer  + token
// 或者通過 ?access_token = token
router.get("/user/user_info",
  passport.authenticate("bearer", { session: false }),
  function(req, res) {
    res.json({username: req.user.name});
});

module.exports = router;
passport配置

./passport.js 配置權(quán)限模塊所需功能

const passport = require("passport");
const Strategy = require("passport-http-bearer").Strategy;

const User = require("./models/user");
const config = require("./config");

module.exports = function(passport) {
    passport.use(new Strategy(
        function(token, done) {
            User.findOne({
                token: token
            }, function(err, user) {
                if (err) {
                    return done(err);
                }
                if (!user) {
                    return done(null, false);
                }
                return done(null, user);
            });
        }
    ));
};

主要驗(yàn)證發(fā)送的token值與用戶服務(wù)器端token值是否匹配,進(jìn)行信息驗(yàn)證。

具體調(diào)試

現(xiàn)在就可以運(yùn)行我們的代碼看具體運(yùn)作過程了!為了便于調(diào)試與參數(shù)的收發(fā),我們使用postman(可在Chrome上或Mac上安裝)來操作.

node index運(yùn)行我們的本地服務(wù)器,訪問 [localhost:8080/]()
應(yīng)該就可以看到我們所返回的初始json值了,然我們繼續(xù)深入測試。

POST訪問[localhost:8080/api/signup](),我們來注冊(cè)一個(gè)新用戶,注意要設(shè)置bodyContent-Typex-www-form-urlencoded 以便我們的body-parser能夠正確解析,好的我們成功模擬創(chuàng)建了我們的新用戶。

連接一下數(shù)據(jù)庫看下我們的用戶信息是否也被正確存儲(chǔ)(注:我使用的是MongoChef,十分強(qiáng)大MongoDB數(shù)據(jù)庫管理軟件),我們可以看到,我的password也被正確加密保存了。

接著POST訪問[localhost:8080/api/user/accesstoken](),來為我的用戶獲得專屬token,POST過程與注冊(cè)相關(guān),可以看到也正確生成我們的token值。

再看下我們的數(shù)據(jù)庫中的用戶信息,token值也被存入了進(jìn)來,便于我們之后進(jìn)行權(quán)限驗(yàn)證。

GET訪問[localhost:8080/api/user/user_info](),同時(shí)將我們的token值在Header中以 Authorization: token 傳入,正確獲得用戶名則表示我們?cè)L問請(qǐng)求通過了驗(yàn)證。

如果token值不正確,則返回HTTP狀態(tài)碼 401 Unauthorized 并拒絕訪問請(qǐng)求。到這里我們的權(quán)限驗(yàn)證功能也就基本實(shí)現(xiàn)了。

總結(jié)

希望在看完這篇教程后能夠?qū)δ阍赗ESTful Api開發(fā)上有所啟發(fā),小生才疏學(xué)淺,過程中有什么不足的地方也歡迎指正。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86863.html

相關(guān)文章

  • Node.js+MongoDB對(duì)于RestfulApi用戶token認(rèn)證實(shí)踐

    摘要:則是目前比較成熟的一套互聯(lián)網(wǎng)應(yīng)用程序的設(shè)計(jì)理論。則允許操作,不一樣,報(bào)錯(cuò)返回或者加入黑名單。再看下我們的數(shù)據(jù)庫中的用戶信息,值也被存入了進(jìn)來,便于我們之后進(jìn)行權(quán)限驗(yàn)證。訪問同時(shí)將我們的值在中以傳入正確獲得用戶名則表示我們?cè)L問請(qǐng)求通過了驗(yàn)證。 showImg(https://segmentfault.com/img/remote/1460000008629635?w=800&h=534)...

    klinson 評(píng)論0 收藏0
  • node技術(shù)棧 - 收藏集 - 掘金

    摘要:異步最佳實(shí)踐避免回調(diào)地獄前端掘金本文涵蓋了處理異步操作的一些工具和技術(shù)和異步函數(shù)。 Nodejs 連接各種數(shù)據(jù)庫集合例子 - 后端 - 掘金Cassandra Module: cassandra-driver Installation ... 編寫 Node.js Rest API 的 10 個(gè)最佳實(shí)踐 - 前端 - 掘金全文共 6953 字,讀完需 8 分鐘,速讀需 2 分鐘。翻譯自...

    王偉廷 評(píng)論0 收藏0
  • 2018最新后端開發(fā)人員的路線圖

    摘要:簡評(píng)之前,后端開發(fā)路線圖僅僅是一個(gè)技術(shù)推薦,且沒有明確的方向指明應(yīng)該遵循的順序,這份重新制作的指南將會(huì)給你一個(gè)更好的方向。現(xiàn)在開始創(chuàng)建一個(gè)包并分發(fā)給其他人使用,并確保遵循迄今為止學(xué)到的標(biāo)準(zhǔn)和最佳實(shí)踐。 簡評(píng):之前,后端開發(fā)路線圖僅僅是一個(gè)技術(shù)推薦,且沒有明確的方向指明應(yīng)該遵循的順序,這份重新制作的指南將會(huì)給你一個(gè)更好的方向。 現(xiàn)在的 Web 開發(fā)與幾年前完全不同了,有很多不同的東西可以...

    王陸寬 評(píng)論0 收藏0
  • 架構(gòu)~微服務(wù)

    摘要:接下來繼續(xù)介紹三種架構(gòu)模式,分別是查詢分離模式微服務(wù)模式多級(jí)緩存模式。分布式應(yīng)用程序可以基于實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布訂閱負(fù)載均衡命名服務(wù)分布式協(xié)調(diào)通知集群管理選舉分布式鎖和分布式隊(duì)列等功能。 SpringCloud 分布式配置 SpringCloud 分布式配置 史上最簡單的 SpringCloud 教程 | 第九篇: 服務(wù)鏈路追蹤 (Spring Cloud Sleuth) 史上最簡單的 S...

    xinhaip 評(píng)論0 收藏0
  • 聊聊畢業(yè)設(shè)計(jì)系列 --- 系統(tǒng)實(shí)現(xiàn)

    摘要:七牛云接入本系統(tǒng)的圖片,音視頻是放在七牛云,所以需要接入七牛云。在服務(wù)端通過接口請(qǐng)求來獲取七牛云上傳,客戶端獲取到七牛云,通過不同方案將帶上。 效果展示 showImg(https://user-gold-cdn.xitu.io/2018/8/26/16576a709bd02f5f?w=1409&h=521&f=gif&s=30128195); showImg(https://user...

    null1145 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<