React 配置文件页面,尝试从后端获取 JSON 数据时如何避免'GET http://localhost:3001/users/profile 401 (Unauthorized)'



对于这个应用程序,我使用React &表达。我在PORT 3000上运行React,在PORT 3001上运行Express。在Express端,我使用JWT进行身份验证。

首先,这是我的auth.js服务文件:
const jwt = require('jsonwebtoken');
const models = require('../models');
const bcrypt = require('bcryptjs');
var authService = {
signUser: function (user) {
const token = jwt.sign({
Username: user.Username,
UserId: user.UserId
},
'secretkey',
{
expiresIn: '1h'
}
);
return token;
},
verifyUser: function (token) {
try {
let decoded = jwt.verify(token, 'secretkey');
return models.users.findByPk(decoded.UserId);
} catch (err) {
console.log(err);
return null;
}
},
hashPassword: function (plainTextPassword) {
let salt = bcrypt.genSaltSync(10);
let hash = bcrypt.hashSync(plainTextPassword, salt);
return hash;
},
comparePasswords: function (plainTextPassword, hashedPassword) {
return bcrypt.compareSync(plainTextPassword, hashedPassword);
}
}
module.exports = authService;

当用户向注册路由发出POST请求时,它工作:

router.post('/signup', function (req, res, next) {
models.users.findOrCreate({
where: {
Username: req.body.username
},
defaults: {
FirstName: req.body.firstName,
LastName: req.body.lastName,
Email: req.body.email,
Password: authService.hashPassword(req.body.password)
}
})
.spread(function (result, created) {
if (created) {
res.redirect("http://localhost:3000/login");
} else {
res.send('This user already exist')
}
});
});

Signup在Postman和React中都可以使用。

当用户向登录路由发出POST请求时,它工作:

router.post('/login', function (req, res, next) {
models.users.findOne({
where: {
Username: req.body.username
}
}).then(user => {
if (!user) {
console.log('User not found')
return res.status(401).json({
message: "Login Failed"
});
} else {
let passwordMatch = authService.comparePasswords(req.body.password, user.Password);
if (passwordMatch) {
let token = authService.signUser(user);
res.cookie('jwt', token);
res.redirect('http://localhost:3001/users/profile');
} else {
console.log('Wrong Password');
}
}
});
});

Login在Postman和React中都可以使用。

当用户向配置文件路由发出GET请求时,它半工作:

router.get('/profile', function (req, res, next) {
let token = req.cookies.jwt;
if (token) {
authService.verifyUser(token).then(user => {
if (user) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(user));
} else {
res.status(401);
res.send('Invalid authentication token');
}
});
} else {
res.status(401);
res.send('Invalid authentication token');
}
});

这只适用于邮差,我可以看到我想要使用邮差的数据。在React中,它不会得到我请求的配置文件路由。这就是错误出现的地方:Console error

在React端,这是profile GET组件:

import React from 'react';
import axios from 'axios';
class UserProfile extends React.Component {
constructor(props) {
super(props);
this.state = {
profileData: []
}
};
fetchProfileData = () => {
var encodedURI = window.encodeURI(this.props.uri);
return axios.get(encodedURI).then(response => {
this.setState(() => {
return {
profileData: response.data
};
});
});
};
componentDidMount() {
this.fetchProfileData();
}
render() {
console.log(this.state.profileData);
if (this.state.profileData.length === 0) {
return <div>Failed to fetch data from server</div>
}
const profile = this.state.profileData.map(user => (
<div key={user.UserId}>Hello world</div>
));
return <div>{profile}</div>
}
}
export default UserProfile;

然后当我要渲染这个组件时,我只需:

<UserProfile uri="http://localhost:3001/users/profile" />

这将呈现"从服务器获取数据失败",然后控制台将记录"401(未经授权)"错误。我只是不能让它在React中渲染。

如果有人想要我的Express app.js文件的一些额外的信息:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var models = require('./models');
var cors = require('cors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(cors());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
models.sequelize.sync().then(function () {
console.log("DB Synced Up");
});
module.exports = app;

提前谢谢你。我一直在努力想弄明白这个问题。

我试着玩弄我的UserProfile组件。我试过在Express中玩我的/profile路由。我得到的唯一2个错误是401(未经授权)和一些关于头。我知道我的JWT密钥被传递到反应端,因为当我执行"localhost:3000/profile"(反应端)时,我可以看到我已经存储了cookie。我不确定如何在React端进行授权。在这一点上,我非常不知道该做什么。这是我第一次尝试用React设置身份验证。我一直使用Express和.hbs文件来呈现我的个人资料页面。但有人告诉我,不应该在后端渲染个人资料页面。所以,这里我尝试用React来做。

我已经将内容从后端呈现到前端,但这并没有使用JWT。我坚信这与JWT cookie有关。我只是不知道如何在React中验证它。再次提前感谢。

我通过将此添加到我的React项目来修复它:

我把这个添加到fetchProfileData()

{ withCredentials: true }

fetchProfileData = () => {
var encodedURI = window.encodeURI(this.props.uri);
return axios.get(encodedURI, { withCredentials: true }).then(response => {
this.setState(() => {
return {
profileData: response.data
};
});
});
};

然后在Express中,我摆弄了一下我的Profile路由。将数据放入数组中,然后发送:

router.get('/profile', function (req, res, next) {
var userData = [];
let token = req.cookies.jwt;
if (token) {
authService.verifyUser(token).then(user => {
userData.push(user);
res.send(userData);
});
} else {
res.status(401);
res.send('Invalid authentication token');
}
});

相关内容

最新更新