0

我正在制作一个具有注册和登录功能的 MERN 应用程序。当我尝试在浏览器中提交表单时,控制台向我显示 400 错误请求。该功能适用​​于后端并返回 200 ok 状态,但不适用于前端。

这是浏览器中的错误图片。

这是我下面的代码

验证

const Validator = require("validator");

const isEmpty = require("is-empty");

module.exports = function validateRegisterInput(data) {
    let errors = {};

    data.name = !isEmpty(data.name) ? data.name : "";
    data.email = !isEmpty(data.email) ? data.email: "";
    data.password = !isEmpty(data.password) ? data.password: "";
    data.password2 = !isEmpty(data.password2) ? data.password2: "";

    if(Validator.isEmpty(data.name)) {
        errors.name = "Name field is Required";
    }

    if(Validator.isEmpty(data.email)) {
        errors.email = "Email field is Required";
    } else if(!Validator.isEmail(data.email)) {
        errors.email = "Email is invalid"
    }

    if (Validator.isEmpty(data.password)) {
        errors.password = "Password field is required";
    }

    if (Validator.isEmpty(data.password2)) {
        errors.password2 = "Confirm password field is required";
    }

    if(!Validator.isLength(data.password, {min: 6, max: 30})){
        errors: password = "Password must be at least 6 characters";
    }

    if(!Validator.equals(data.password, data.password2)){
        errors.password2 = "Password must match"
    }

    return {
        errors,
        isValid: isEmpty(errors)
    };

    
};

控制器

const express = require("express");

const router = express.Router();

const bcrypt = require("bcryptjs");

const jwt = require ("jsonwebtoken");

const keys = require("../../config/key");


const validateRegisterInput = require("../../validation/register");
const validateLoginInput = require("../../validation/login");


const User = require("../../models/User");


router.post("/register", (req, res) => {





//FORM VALIDATION

const {errors, isValid } = validateRegisterInput(req.body)


//CHECK VALIDATION

if(!isValid) {
    return res.status(400).json(errors)
}

User.findOne({ email: req.body.email }).then( returnedUser => {
    
    if(returnedUser) {
        return res.status(400).json({email: "Email already exists"});
    }
});


// saving user with request information to database
const newUser = new User({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
});

bcrypt.genSalt(10, (err, salt)=>{
    bcrypt.hash(newUser.password, salt, (err, hash)=>{
        if(err) throw err;
        newUser.password = hash;

        newUser
            .save()
            .then(user => res.json(user))
            .catch(err => console.log(err));
        });
    });

});







router.post("/login", (req, res)=>{


const {errors, isValid} = validateLoginInput(req.body)
if(!isValid){
    return res.status(400).json(errors)
}

const email = req.body.email;
const password = req.body.password


User.findOne({ email: email }).then(user =>{

    if(!user){
        return res.status(404).json({ emailNotFound: "Email not found"});
    }

    bcrypt.compare(password, user.password).then(isMatch => {
        if(isMatch){


            const payload = { id: user.id, name: user.name };

            jwt.sign(payload, 
                keys.secretOrKey, 
                {expiresIn: 31556926}, 
                (err, token) => {
                    res.json({ success: true, token: "Bearer " + token });
            });
        } else {
            return res.status(400)
            .json({passwordincorrect: "password incorrect"})
        }
    })
})

});
module.exports = router;

行动

import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";
import {
  GET_ERRORS,
  SET_CURRENT_USER,
  USER_LOADING
} from "./types";
// Register User

export const registerUser = (userData, history) => dispatch => {
  axios.post("/api/users/register", userData)
    .then(res => history.push("/login")) // re-direct to login on successful register
    .catch(err =>
      dispatch({
        type: GET_ERRORS,
        payload: err.response.data
      })
    );
};

// Login - get user token
export const loginUser = userData => dispatch => {
  axios
    .post("/api/users/login", userData)
    .then(res => {
      // Save to localStorage
// Set token to localStorage
      const { token } = res.data;
      localStorage.setItem("jwtToken", token);
      // Set token to Auth header
      setAuthToken(token);
      // Decode token to get user data
      const decoded = jwt_decode(token);
      // Set current user
      dispatch(setCurrentUser(decoded));
    })
    .catch(err =>
      dispatch({
        type: GET_ERRORS,
        payload: err.response.data
      })
    );
};
// Set logged in user
export const setCurrentUser = decoded => {
  return {
    type: SET_CURRENT_USER,
    payload: decoded
  };
};
// User loading
export const setUserLoading = () => {
  return {
    type: USER_LOADING
  };
};
// Log user out
export const logoutUser = () => dispatch => {
  // Remove token from local storage
  localStorage.removeItem("jwtToken");
  // Remove auth header for future requests
  setAuthToken(false);
  // Set current user to empty object {} which will set isAuthenticated to false
  dispatch(setCurrentUser({}));
};

零件

import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { registerUser } from "../../actions/authActions";
import classnames from "classnames";

class Register extends Component {
  constructor() {
    super();
    this.state = {
      name: "",
      email: "",
      password: "",
      password2: "",
      errors: {},
    };
  }

  componentDidMount() {
    // If logged in and user navigates to Register page, should redirect them to dashboard
    if (this.props.auth.isAuthenticated) {
      this.props.history.push("/dashboard");
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.errors) {
      this.setState({
        errors: nextProps.errors,
      });
    }
  }

  onChange = (e) => {
    this.setState({ [e.target.id]: e.target.value });
  };

  onSubmit = (e) => {
    e.preventDefault();

      const newUser = {
        name: this.state.name,
        email: this.state.email,
        password: this.state.password,
        password2: this.state.password2,
      };

    console.log(newUser);
    this.props.registerUser(newUser, this.props.history);
  };
  render() {
    const { errors } = this.state;
    return (
      <div className="container">
        <div className="row">
          <div className="col s8 offset-s2">
            <Link to="/" className="btn-flat waves-effect">
              <i className="material-icons left">keyboard_backspace</i> Back to
              home
            </Link>
            <div className="col s12" style={{ paddingLeft: "11.250px" }}>
              <h4>
                <b>Register</b> below
              </h4>
              <p className="grey-text text-darken-1">
                Already have an account? <Link to="/login">Log in</Link>
              </p>
            </div>
            <form noValidate onSubmit={this.onSubmit}>
              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.name}
                  error={errors.name}
                  id="name"
                  type="text"
                  className={classnames("", {
                    invalid: errors.name
                  })}
                />
                <label htmlFor="name">Name</label>
                <span className="red-text">{errors.name}</span>
              </div>
              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.email}
                  error={errors.email}
                  id="email"
                  type="email"
                  className={classnames("", {
                    invalid: errors.email
                  })}
                />
                <label htmlFor="email">Email</label>
                <span className="red-text">{errors.email}</span>
              </div>
              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.password}
                  error={errors.password}
                  id="password"
                  type="password"
                  className={classnames("", {
                    invalid: errors.password
                  })}
                />
                <label htmlFor="password">Password</label>
                <span className="red-text">{errors.password}</span>
              </div>
              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.password2}
                  error={errors.password2}
                  id="password2"
                  type="password"
                  className={classnames("", {
                    invalid: errors.password2
                  })}
                />
                <label htmlFor="password2">Confirm Password</label>
                <span className="red-text">{errors.password2}</span>
              </div>
              <div className="col s12" style={{ paddingLeft: "11.250px" }}>
                <button
                  style={{
                    width: "150px",
                    borderRadius: "3px",
                    letterSpacing: "1.5px",
                    marginTop: "1rem",
                  }}
                  type="submit"
                  className="btn btn-large waves-effect waves-light hoverable blue accent-3"
                >
                  Sign up
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

Register.propTypes = {
  registerUser: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  auth: state.auth,
  errors: state.errors,
});

export default connect(mapStateToProps, { registerUser })(withRouter(Register));

这里是根服务器

const express = require("express");

const mongoose = require("mongoose");

const bodyParser = require("body-parser");

const passport = require("passport");


const app = express();
const users = require("./controllers/api/users")


app.use(

    bodyParser.urlencoded({
        extended: false
    })
);

//DATA BASE CONFIGURATION

const dbkeys = require("./config/key").mongoURI;

mongoose.connect( 
    dbkeys, 
    {useNewUrlParser: true} )

        .then(()=> console.log("database connection successful"))
        .catch(err => console.log(err))

app.use(passport.initialize());
require("./config/passport")(passport);


app.use("/api/users", users);


const port = 5000;

app.listen( port, () => console.log("server us up and running on port 5000!"))

4

1 回答 1

0

Axios 以 JSON ( application/json) 形式发送数据。您目前只使用 body 解析器urlencoded,它指的是默认使用application/x-www-form-urlencoded的数据格式。<form>

您还需要使用bodyParser.json()

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

app.use(bodyParser.json());
于 2021-01-09T00:59:01.637 回答