繁体   English   中英

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

[英]React profile page, how to avoid 'GET http://localhost:3001/users/profile 401 (Unauthorized)' when trying to get JSON data from back end

对于这个应用程序,我使用的是 React & Express。 我在端口 3000 上运行 React,在端口 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')
      }
    });
});

注册适用于 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');
      }
    }
  });
});

登录适用于 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');
  }
});

这仅适用于 Postman,我可以使用 Postman 看到我想要的数据。在 React 中,它不会获取我请求的配置文件路由。 这是错误的来源:控制台错误

在 React 端,这是配置文件 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;

然后当我 go 渲染这个组件时,我只是:

<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 和 the.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');
    }
 });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM