How to ignore some request type in Jsonwebtoken

2019-07-13 10:54发布

问题:

I want to ignore some API URL of being checked against token authentication

I want to protect post and put methods but not get of this url

localhost:3000/api/events/

router.use(function(request, response) {
    var token = request.body.token || request.query.token || request.headers['x-access-token'];
    if (token) {
        jwt.verify(token, app.get(superSecret), function(err, decoded) {
            if (err)
                return response.json({
                    sucess: false,
                    message: "Failed token Authentication"
                });
            else {
                request.decoded = decoded;
                next();
            }

        });
    } else {
        return response.status(403).send({
            success: false,
            message: 'No token provided.'
        });

    }

});

How can I do this using jsonwebtoken in node,express

I want this to apply to only post,put,delete requests but not on get requests.

回答1:

You can move your anonymous middleware to normal declared function and then pass it to all protected routes (you decide which route you want to protect!)

Your code could look like:

function tokenProtection(request, response, next) {
    var token = request.body.token || request.query.token || request.headers['x-access-token'];
    if (token) {
        jwt.verify(token, app.get(superSecret), function(err, decoded) {
            if (err)
                return response.json({
                    sucess: false,
                    message: "Failed token Authentication"
                });
            else {
                request.decoded = decoded;
                next();
            }

        });
    } else {
        return response.status(403).send({
            success: false,
            message: 'No token provided.'
        });

    }

}

and now your routes could look like (your decision what you want to protect):

router.get('/item', function(req, res) { ... }); // not protected
router.get('/item/:id', function(req, res) { ... }); // not protected
router.post(tokenProtection,'/item', function(req, res) { ... });//protected
router.put(tokenProtection,'/item', function(req, res) { ... });//protected

router.get('/book', function(req, res) { ... });// not protected
router.get('/book/:id', function(req, res) { ... });// not protected
router.post(tokenProtection,'/book', function(req, res) { ... });//protected
router.put(tokenProtection,'/book', function(req, res) { ... });//protected


回答2:

Put the routes you want to protect below your authentication route and the ones you do not want to protect can above the authentication route. Something like this,

    // Require what will be needed 
    var express  =  require('express'),
    User     =  require('../models/user'),
    usersRouter   =  express.Router();

    var jwt    = require('jsonwebtoken'); // used to create, sign, and verify tokens
    var config = require('./config'); // get our config file

    var secret = {superSecret: config.secret}; // secret variable,

    // Create a new user and return as json for POST to '/api/users'
    usersRouter.post('/', function (req, res) {
      var user = new User(req.body);
      user.save(function(){ //pre-save hook will be run before user gets saved. See user model.
        res.json({user : user, message: "Thank You for Signing Up"});

      });
    });

    usersRouter.post('/authentication_token', function(req, res){
      var password = req.body.password;
      // find the user
        User.findOne({
          email: req.body.email
        }, function(err, user) {
          //If error in finding the user throw the error
          if (err) throw err;
          //If there is no error and the user is not found.
          if (!user) {
            res.json({ success: false, message: 'Authentication failed. User not found.' });
            //if the user is found
          } else if (user) {
            // check if password matches
            user.authenticate(password, function(isMatch){
              if(isMatch){
                // if user is found and password is right
                // create a token with full user object. This is fine because password is hashed. JWT are not encrypted only encoded.
                var token = jwt.sign({email: user.email}, secret.superSecret, {
                  expiresIn: 144000 
                });
                // set the user token in the database
                user.token = token;
                user.save(function(){
                  // return the information including token as JSON
                  res.json({
                    success: true,
                    id: user._id,
                    message: 'Enjoy your token!',
                    token: token
                  });
                });
              } else {
                res.json({ success: false, message: 'Authentication failed. Wrong password.' });
              }
            });
          }
        });
      });

//***********************AUTHENTICATED ROUTES FOR USERS******************************

      // Return ALL the users as json to GET to '/api/users'
    usersRouter.get('/', function (req, res) {
      User.find({}, function (err, users) {
        res.json(users);
      });
    });

    // Export the controller
    module.exports = usersRouter;

I actually explained this yesterday itself on my blog because I was struggling to figure it out. If you are still not clear, you can check it out here, Node API Authentication with JSON Web Tokens - the right way.

If there are other resources like in my case it was plans. Below is the code I put above all the routes for plans I wanted to authenticate.

    // route middleware to verify a token. This code will be put in routes before the route code is executed.
PlansController.use(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'];

  // If token is there, then decode token
  if (token) {

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

  } else {

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

  }
});
    //***********************AUTHENTICATED ROUTES FOR PLAN BELOW******************************
PlansController.get('/', function(req, res){
  Plan.find({}, function(err, plans){
  res.json(plans);
  });
});