node.js - 如何使用受保护的 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;
解决方案
您应该仅在 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 令牌。
推荐阅读
- c++ - 数组错误以存储数字排序算法程序的随机变量值
- python - 按名称将节点插入到特定级别的 ElementTree 树
- python - 使用 Pandas 将 2 列名称转换为 4 列名称
- java - 来自 Java 代码的 Intellij 自定义语言插件参考
- javascript - 在javascript中处理跨模块的相对路径
- azure - 多个 Runbook 可以在 Azure 自动化帐户中同时运行吗?
- c - 以前的值仍然存储在 do while 循环的下一次迭代中
- batch-file - 如何在 .bat 脚本中获取正在运行的 cmd 窗口日志
- python - 在 DoE 期间重置每个输入之间的所有变量以进行多学科分析
- mysql - 同一张表上多对多关系的内部联接