首页 > 解决方案 > 如何使用受保护的 api 路由并使用 Nodejs 验证 JWT 令牌?

问题描述

我正在尝试实现一个注册和登录系统,目前我能够在数据库中注册和存储数据,并且也可以登录,因为我已经测试过它,我用 aconsole.log(token);来查看我是否是一个令牌。然而,在登录后,我进入了我的网页(React 组件)/Profile,它获取了一个 GET users/current,但我在控制台中收到了这个。

GET /users/current 401 2.083 ms - 33

同样在我的浏览器控制台中

 Uncaught (in promise) SyntaxError: Unexpected token A in JSON at position 0

我觉得令牌没有正确传递,我是使用 JWT 的新手,所以任何帮助都是有用的。

服务器.js

var express = require('express');
var cors = require('cors');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 5000;
var morgan = require('morgan');
const auth = require('./middleware/auth');
const User = require('./models/User');

app.use(bodyParser.json());
app.use(cors());
app.use(
  bodyParser.urlencoded({
    extended: false
  })
);

// use morgan to log requests to the console
app.use(morgan('dev'));

var Users = require('./routes/Users');

app.use('/users', Users);

// Create a Server
const PORT = process.env.PORT || 5000; // Environment variable or port 5000

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

用户.js

const express = require('express');
const users = express.Router();
const cors = require('cors');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const bodyParser = require('body-parser');
const User = require('../models/User');
const config = require('config');
const auth = require('../middleware/auth');


users.use(
  bodyParser.urlencoded({
    extended: true
  })
);

users.use(bodyParser.json());

users.use(cors());

users.post('/register', (req, res) => {
  const today = new Date();
  const userData = {
    first_name: req.body.first_name,
    last_name: req.body.last_name,
    email: req.body.email,
    password: req.body.password,
    created: today
  };

  User.findOne({
    where: {
      email: req.body.email
    }
  })
    //TODO bcrypt
    //Need validation to appear on console and in view
    .then(user => {
      if (!user) {
        bcrypt.hash(req.body.password, 10, (err, hash) => {
          userData.password = hash;
          User.create(userData)
            .then(user => {
              res.json({ status: user.email + 'Registered!' });
            })
            .catch(err => {
              res.send('error: ' + err);
            });
        });
      } else {
        res.json({ error: 'User already exists' });
      }
    })
    .catch(err => {
      res.send('error: ' + err);
    });
});

users.post('/authenticate', (req, res) => {
  User.findOne({
    where: {
      email: req.body.email
    }
  }).then(user => {
    if (user) {
      if (bcrypt.compareSync(req.body.password, user.password)) {
        const payload = {
          check: true
        };

        const token = jwt.sign(payload, config.get('myprivatekey'), {
          expiresIn: 1440 // expires in 24 hours
        });

        res.json({
          message: 'authentication done ',
          token: token
        });
        console.log('Successful Login');
        console.log(user.first_name);
      } else {
        res.json({ message: 'please check your password !' });
        console.log('incorrect password');
      }
    } else {
      res.json({ message: 'user not found !' });
      console.log('user cannot be found');
    }
  });
});

users.get('/current', auth, async (req, res) => {
  const user = await User.findById(req.user._id).select('-password');
  console.log(user);
  res.send(user);
});

Auth.js

const jwt = require('jsonwebtoken');
const config = require('config');

module.exports = function(req, res, next) {
  //get the token from the header if present
  const token = req.headers['x-access-token'] || req.headers['authorization'];
  //if no token found, return response (without going to the next middelware)
  if (!token) return res.status(401).send('Access denied. No token provided.');

  try {
    //if can verify the token, set req.user and pass to next middleware
    const decoded = jwt.verify(token, config.get('myprivatekey'));
    req.user = decoded;
    next();
  } catch (ex) {
    //if invalid token
    res.status(400).send('Invalid token.');
  }
};

/Profile 网页(React 组件)

import React, { Component } from 'react';
import jwt_decode from 'jwt-decode';
import axios from 'axios';

class Profile extends Component {
  constructor() {
    super();
    this.state = {
      first_name: '',
      last_name: '',
      email: '',
      errors: {}
    };
  }

  componentDidMount() {
    fetch('http://localhost:5000/users/current')
      .then(function(response) {
        return response.json();
      })
      .then(function(myJson) {
        console.log(JSON.stringify(myJson));
      });
  }

  render() {
    return (
      <div className='container'>
        <div className='jumbotron mt-5'>
          <div className='col-sm-8 mx-auto'>
            <h1 className='text-center'>PROFILE</h1>
          </div>
          <table className='table col-md-6 mx-auto'>
            <tbody>
              <tr>
                <td>First Name</td>
                <td>{this.state.first_name}</td>
              </tr>
              <tr>
                <td>Last Name</td>
                <td>{this.state.last_name}</td>
              </tr>
              <tr>
                <td>Email</td>
                <td>{this.state.email}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

export default Profile;

标签: node.jsreactjsjwt

解决方案


您应该仅在 server.js 中使用 cors 和 bodyparser 的代码。无需在 User.js 中使用它。使用 express-jwt 进行 JWT 身份验证。

var jwt = require('express-jwt');

users.get('/current', jwt({secret: config.get('myprivatekey')}), async (req, res) => {
  const user = await User.findById(req.user._id).select('-password');
  console.log(user);
  res.send(user);
});

请参考https://www.npmjs.com/package/express-jwt

还要在标头中发送令牌以进行获取

fetch('http://localhost:5000/users/current', {
    method: 'GET',
    mode: 'cors',
    headers: {
        'Authorization': 'Bearer xxxxx.yyyyy.zzzzz',
    },
})

请替换xxxxx.yyyyy.zzzzz为 JWT 令牌。


推荐阅读