2017-04-24 146 views
0

這是一件令人困惑的事情。我。讓我們假設您有一個REST API,您希望用戶註銷。登錄後,應該銷燬jwt(json Web令牌),以便用戶無法訪問服務器的資源(即菜單,菜餚等)。銷燬JSON Web令牌

在我的情況下,用戶可以註銷,但是他/她仍然可以執行所有的請求(獲得盤點,發佈和刪除),直到令牌有效。這是我的代碼。

verify.js

var User = require('../models/user'); 
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens 
var config = require('../config.js'); 

exports.getToken = function (user) { 
     return jwt.sign(user, config.secretKey, { 
      expiresIn: 3600 
     }); 
}; 

exports.verifyOrdinaryUser = function (req, res, next) { 
    // check header or url parameters or post parameters for token 
    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.secretKey, function (err, decoded) { 
      if (err) { 
       var err = new Error('You are not authenticated!'); 
       err.status = 401; 
       return next(err); 
      } else { 
       // if everything is good, save to request for use in other routes 
       req.decoded = decoded; 
       next(); 
      } 
     }); 
    } else { 
     // if there is no token 
     // return an error 
     var err = new Error('No token provided!'); 
     err.status = 403; 
     return next(err); 
    } 
}; 

我無效1小時後,該令牌。

users.js在那裏我設置所有的路線與他們的任務。即localhost:3000/users/login,localhost:3000/users/register and localhost:3000/users/logout。所以。

var express = require('express'); 
var router = express.Router(); 
var passport = require('passport'); 
var User = require('../models/user'); 
var Verify = require('./verify'); 
/* GET users listing. */ 
router.get('/', function(req, res, next) { 
    res.send('respond with a resource'); 
}); 

router.post('/register', function(req, res) { 
    User.register(new User({ username : req.body.username }), 
    req.body.password, function(err, user) { 
     if (err) { 
      return res.status(500).json({err: err}); 
     } 
     passport.authenticate('local')(req, res, function() { 
      return res.status(200).json({status: 'Registration Successful!'}); 
     }); 
    }); 
}); 

router.post('/login', function(req, res, next) { 
    passport.authenticate('local', function(err, user, info) { 
     if (err) { 
     return next(err); 
     } 
     if (!user) { 
     return res.status(401).json(
      err: info 
      }); 
     } 
     req.logIn(user, function(err) { 
     if (err) { 
      return res.status(500).json({ 
      err: 'Could not log in user' 
      }); 
     } 

     var token = Verify.getToken(user); 
     res.status(200).json({ 
     status: 'Login successful!', 
     success: true, 
     token: token 
     }); 
    }); 
})(req,res,next); 
}); 

router.get('/logout', function (req, res) { 
    req.logout(); 
    res.status(200).json({ 
     status: 'Bye!' 
    }); 
}); 

module.exports = router; 

看來,註銷方法req.logout,不工作:(。任何想法?

感謝,

西奧。

回答

2

你不能註銷如果所有的數據都在客戶端,那麼你需要在服務器上存儲一些狀態來區分你明確註銷的用戶和你沒有註冊的用戶,並且每次檢查這個狀態。所有的數據都是enti依賴JWT令牌,那麼你不能做任何事情使其失效(除了改變你的祕密,這將使所有的令牌無效,而不僅僅是這個)。

實際上,您發現完全基於令牌本身包含的數據使用身份驗證的主要缺點。這些令牌不能失效。一旦他們出來,那麼必須被認爲是積極的。你只能要求客戶忘記,但客戶不能信任這樣做。

從理論上講,您可能擁有一個像Redis這樣的快速數據存儲區,您可以在其中保留所有有效令牌並從中刪除令牌以強制註銷,並在每個請求上檢查此存儲以瞭解誰仍然登錄,誰不是,但是如果你這樣做,那麼你可能會將會話數據存儲在Redis中,並且只給該客戶端的數據存儲提供一些隨機密鑰。

2

智威湯遜被設計爲無國籍。這意味着所有需要的信息都包含在令牌本身中。

由於令牌已經創建,註銷將不會影響此的有效性。

這使您需要保留「無效」令牌的列表,這意味着您再次引入了狀態。

如果您只關注後續用戶在同一臺​​計算機上,則可以在註銷時刪除該令牌,從而保留無狀態,但這不會防止令牌被捕獲的情況。

+0

那麼如何刪除令牌?它有什麼功能嗎? – Theo

+0

我認爲這是最好的解決方案。想象一下你的應用程序有30萬登錄用戶。跟蹤所有這些令牌是不可能的。 – Theo

+0

@他們正在刪除令牌 - 這取決於它如何被存儲爲cookie或本地存儲。重新使用30,000個用戶; a)你只需要跟蹤那些已經註銷的人,可能數量要小得多,b)如果你擔心被捕獲的令牌,減少安全性以減少資源使用量通常是一個壞主意。 – Orangesandlemons