2017-05-28 98 views
1

我正在嘗試在nodejs中構建一個簡單的web令牌protected api。我一直在關注本教程authenticate a node js api with json web tokens,並一直在我的應用中實施這些步驟。我現在有一個允許我獲取/發佈/放置/刪除的api運行,併爲用戶生成webtoken並以純文本形式顯示它(用於開發目的)。我正在使用節點restful api的,但我有一些麻煩理解如何實際驗證客戶端是否發送webtoken在他們的請求,允許這些get/post/put/delete請求之前。使用Json Web令牌的Node-Restful

這是我的路由器。在那裏我定義允許的請求:

const express = require('express') 
const router = express.Router() 

// Models - Load models here 
var userModel = require('./models/User') 

// Controllers - Load controllers here 
const userController = require('./controllers/userController') 

// Routes - Define routes here 
router.post('api/authenticate', userController.authenticate) //Route that generates the webkey and shows it in the response 

// Configure the endpoint that node-restful will expose. Here I want to first check if the user is sending his or her api key. Before allowing these methods. 
userModel.methods(['get', 'put', 'post', 'delete']) 
userModel.register(router, '/api/users') 

// Export the router object 
module.exports = router 

這裏是我的userController生成令牌。

// Dependencies 
const User = require('../models/User') 
const jwt = require('jsonwebtoken') 
const config = require('../config.js') 

module.exports = { 
    authenticate: function(req, res, next) { 
    // find the user 
    User.findOne({username: req.body.name}, function(err, user) { 

     if (err) throw err; 

     if (!user) { 
     res.json({ 
      success: false, 
      message: 'Authentication failed. User not found.' }); 

     } else if (user) { 
     // check if password matches 
     if (user.password != req.body.password) { 
      res.json({ 
      success: false, 
      message: 'Authentication failed. Wrong password.' }); 

     } else { 
      // if user is found and password is right 
      // create a token 
      var token = jwt.sign(user, config.secret, { 
      expiresIn: 60*60*24 // expires in 24 hours 
      }); 

      // return the information including token as JSON 
      res.json({ 
      success: true, 
      message: 'Enjoy your token!', 
      token: token 
      }); 
     } 
     } 
    }) 
    } 
} 

這裏是我的用戶模型。

// Dependencies 
const restful = require('node-restful') 
const mongoose = restful.mongoose 

// Schema 
const userSchema = new mongoose.Schema({ 
    username: String, 
    password: String, 
    email: String 
}) 

// Return the model as a restful model to allow it being used as a route. 
module.exports = restful.model('User', userSchema) 

是否有某種方式可以保護這些端點,使用與我目前使用的相同的語法來公開它們?我相信我會定義方法之前,請檢查網絡令牌:

userModel.methods(['get', 'put', 'post', 'delete']) 
userModel.register(router, '/api/users') 

如果我只是刪除方法本身,用戶將無法獲得頁面,並顯示一個:「不能GET/api/users「錯誤。如果我想顯示自定義錯誤怎麼辦?例如:「沒有提供Web令牌,註冊認證」等等?任何幫助深表感謝。先謝謝你。

我現在有一個函數可以在服務頁面之前檢查令牌。它似乎現在工作。目前,我在postman中手動傳遞令牌作爲頭文件:x-access-token。如何在生成時捕獲令牌並自動讓客戶端在未來的請求中發送令牌?這是檢查令牌和受保護路由的函數。

太好了。我在等待任何答案的同時繼續工作,並完成了此步驟。我現在可以生成令牌並使用郵遞員傳遞給我創建的安全路線。它的工作原理非常完美,但我很努力地理解我將如何在客戶端保存令牌並在每個請求上傳遞該令牌。我仍然生成令牌,如上所述。我可以通過手動將它作爲x-access-token傳遞給我的頭部來驗證令牌,但我該如何自動執行此操作?

更新

這裏是檢查利用該功能的令牌和一個受保護的路由功能:

//路線 - 這裏定義路線

function getToken(req, res, next) { 

    var token = req.body.token || req.query.token || req.headers['x-access-token']; 

    // decode token 
    if (token) { 

     // verifies secret and checks exp 
     jwt.verify(token, config.secret, function(err, decoded) {  
     if (err) { 
      return res.json({ success: false, message: 'Failed to authenticate token.' });  
     } else { 
      // if everything is good, save to request for use in other routes 
      req.decoded = decoded; 
      console.log(decoded);  
      next(); 
     } 
     }); 

    } else { 

     // if there is no token 
     // return an error 
     return res.status(403).send({ 
      success: false, 
      message: 'No token provided.' 
     }); 

    } 

} 

router.get('/entries', getToken, entryController.get) 

我發現這個問題save-token-in-local-storage-using-node解決了最後一塊難題。

回答

1

你可以簡單地爲這種目的編寫一箇中間件。客戶端通常會在標題中發送令牌,以便您可以獲取標題信息並進行驗證。你的中間件會是這樣的。

module.exports = (req, res, next) => { 
 
    
 
\t if (!req.headers.authorization) { 
 
\t \t return res.status(401).json({ 
 
\t \t \t success: false, 
 
\t \t \t message: "You are not authorized for this operation." 
 
\t \t }) 
 
\t } 
 

 
\t // get the authorization header string 
 
\t const token = req.headers.authorization 
 

 
\t // decode the token using a secret key-phrase 
 
\t return jwt.verify(token, config.secret, (err, decoded) => { 
 
\t \t 
 
\t \t // the 401 code is for unauthorized status 
 
\t \t if (err) { 
 
     return res.status(401).json({ 
 
     success: false, 
 
     message: "You are not authorized for this operation." 
 
     }) 
 
    } 
 

 
\t \t const username = decoded.username 
 

 
\t \t // check if a user exists 
 
\t \t return User.findOne({username: username}, (userErr, user) => { 
 

 
\t \t \t if (userErr) { 
 
\t \t \t \t return res.status(500).json({ 
 
\t \t \t \t \t success: false, 
 
\t \t \t \t \t message: "Error occured while processing. Please try again.", 
 
\t \t \t \t \t err: userErr 
 
\t \t \t \t }) 
 
\t \t \t } 
 

 
\t \t \t if (!user) { 
 
\t \t \t \t return res.status(401).json({ 
 
\t \t \t \t \t success: false, 
 
\t \t \t \t \t message: "You are not authorized for this operation." 
 
\t \t \t \t }) 
 
\t \t \t } 
 
    
 
\t \t \t return next() 
 
\t \t }) 
 
\t }) 
 
}

爲了安全起見,最好是存放在JWTs您與用戶相關的應用程序。完整的解釋可以在here找到。

更新: 您可以將令牌保存在cookie中,並解析cookie以找出令牌,然後驗證該令牌。

+0

太好了。我在等待任何答案的同時繼續工作,並完成了此步驟。我現在可以生成令牌並使用郵遞員傳遞給我創建的安全路線。它的工作原理非常完美,但我很努力地理解我將如何在客戶端保存令牌並在每個請求上傳遞該令牌。我仍然生成令牌,如上所述。我可以通過手動將它作爲x-access-token傳遞給我的頭部來驗證令牌,但我該如何自動執行此操作?檢查我的更新問題的代碼。 – n0rd

+0

查看已更新的答案。 – Tolsee

+0

太棒了。我想知道這是否是我應該做的。所以我需要將這個標記保存爲一個cookie,這應該不是我目前在我的令牌生成中使用的json響應。它是否正確? – n0rd