Аутентификация с JWT с использованием Node и React - PullRequest
0 голосов
/ 16 июня 2019

Поэтому я пытаюсь реализовать логику входа в систему с узлом и реагировать, используя монго в качестве базы данных.Сигин в порядке, я подписываю пользователя, и он сохраняется в БД с токеном в браузере.Затем меня перенаправляют на страницу входа в систему, и он говорит, что у меня нет авторизации, даже если у меня сохранен токен.

const mongoose = require('mongoose');
const passport = require('passport');
const router = require('express').Router();
const auth = require('../auth');
const Users = mongoose.model('Users');

//POST new user route (optional, everyone has access)
router.post('/', auth.optional, (req, res, next) => {
    const {
        body: {
            user
        }
    } = req;

    if (!user.email) {
        return res.status(422).json({
            errors: {
                email: 'is required',
            },
        });
    }

    if (!user.password) {
        return res.status(422).json({
            errors: {
                password: 'is required',
            },
        });
    }

    const finalUser = new Users(user);

    finalUser.setPassword(user.password);

    return finalUser.save()
        .then(() => res.json({
            user: finalUser.toAuthJSON()
        }));
});

//POST login route (optional, everyone has access)
router.post('/login', auth.optional, (req, res, next) => {
    const {
        body: {
            user
        }
    } = req;

    if (!user.email) {
        return res.status(422).json({
            errors: {
                email: 'is required',
            },
        });
    }

    if (!user.password) {
        return res.status(422).json({
            errors: {
                password: 'is required',
            },
        });
    }

    return passport.authenticate('local', {
        session: false
    }, (err, passportUser, info) => {
        if (err) {
            return next(err);
        }

        if (passportUser) {
            const user = passportUser;
            user.token = passportUser.generateJWT();

            return res.json({
                user: user.toAuthJSON()
            });
        }

        return status(400).info;
    })(req, res, next);
});

//GET current route (required, only authenticated users have access)
router.get('/current', auth.required, (req, res, next) => {
    const {
        payload: {
            id
        }
    } = req;

    return Users.findById(id)
        .then((user) => {
            if (!user) {
                return res.sendStatus(400);
            }

            return res.json({
                user: user.toAuthJSON()
            });
        });
});

module.exports = router;
const jwt = require('express-jwt');

const getTokenFromHeaders = (req) => {
    const {
        headers: {
            authorization
        }
    } = req;

    if (authorization && authorization.split(' ')[0] === 'Token') {
        return authorization.split(' ')[1];
    }
    return null;
};

const auth = {
    required: jwt({
        secret: 'secret',
        userProperty: 'payload',
        getToken: getTokenFromHeaders,
    }),
    optional: jwt({
        secret: 'secret',
        userProperty: 'payload',
        getToken: getTokenFromHeaders,
        credentialsRequired: false,
    }),
};

module.exports = auth;

Это логика пользователей и аутентификации на моей стороне сервера с Node.

import React, { Component } from "react";
import { getJWT } from "../../helpers/jwt";
import axios from "axios";
import { withRouter } from "react-router";

export class Auth extends Component {
  constructor(props) {
    super(props);

    this.state = {
      user: undefined
    };
  }

  componentDidMount() {
    const jwt = getJWT();
    if (!jwt) {
      this.props.history.push("/Signup");
    }

    axios
      .get("http://localhost:3000/api/users/current", {
        headers: {
          Authorization: `Token ${jwt}`
        }
      })
      .then(res => {
        console.log(res);
        this.setState({
          user: res.data.user
          // user: {
          //   email: this.state.user.email,
          //   password: this.state.user.password
          // }
        });
        console.log(this.setState);
      })
      .catch(err => {
        console.log(err);

        localStorage.removeItem("cool-jwt");
        debugger;
        this.props.history.push("/Protected");
      });
  }
  render() {
    if (this.state.user === undefined) {
      return (
        <div>
          <h1> Loading... </h1>{" "}
        </div>
      );
    }

    return <div> {this.props.children} </div>;
  }
}

export default withRouter(Auth);

Это моя авторизация во внешнем интерфейсе.

import React, { Component } from "react";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import Container from "@material-ui/core/Container";
import Link from "@material-ui/core/Link";
import Grid from "@material-ui/core/Grid";
import { ValidatorForm, TextValidator } from "react-material-ui-form-validator";
import { classes } from "../constants/login";
import axios from "axios";

export class Signup extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: "",
      // repeatPassword: "",
      errorText: ""
    };

    this.change = this.change.bind(this);
    this.submit = this.submit.bind(this);
  }

  change(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  // componentDidMount() {
  //   // custom rule will have name 'isPasswordMatch'
  //   ValidatorForm.addValidationRule("isPasswordMatch", value => {
  //     if (value !== this.state.password) {
  //       return false;
  //     }
  //     return true;
  //   });
  // }

  // componentWillUnmount() {
  //   // remove rule when it is not needed
  //   ValidatorForm.removeValidationRule("isPasswordMatch");
  // }

  submit(e) {
    e.preventDefault();
    axios
      .post("http://localhost:3000/api/users", {
        user: {
          email: this.state.email,
          password: this.state.password
        }
      })
      .then(res => {
        debugger;
        localStorage.setItem("cool-jwt", res.data.user.token);
        console.log(res.data.user.token);
        this.props.history.push("/Login");
      });
  }

  render() {
    return (
      <div>
        <Container component="main" maxWidth="xs">
          <CssBaseline />
          <div className={classes.paper}>
            <Avatar
              alt="IPCA"
              src="http://i68.tinypic.com/2gspvkm.png"
              className={classes.bigAvatar}
            />{" "}
            <Typography component="h1" variant="h5">
              Sign up
            </Typography>{" "}
            <ValidatorForm
              ref="form"
              className={classes.form}
              noValidate
              onSubmit={e => this.submit(e)}
            >
              <TextValidator
                variant="outlined"
                margin="normal"
                required
                fullWidth
                id="email"
                label="Insert your email"
                name="email"
                autoComplete="email"
                autoFocus
                onChange={e => this.change(e)}
                value={this.state.email}
                validators={["required"]}
                errorMessages={["this field is required"]}
              />{" "}
              <TextValidator
                variant="outlined"
                margin="normal"
                required
                fullWidth
                name="password"
                label="Insert your Password"
                type="password"
                id="password"
                autoComplete="current-password"
                onChange={e => this.change(e)}
                value={this.state.password}
                onBlur={this.isDisabled}
                validators={["required"]}
                errorMessages={["this field is required"]}
              />{" "}
              {/* <TextValidator
                variant="outlined"
                margin="normal"
                required
                fullWidth
                name="password"
                label="Repeat your Password"
                type="password"
                id="password"
                autoComplete="current-password"
                onChange={e => this.change(e)}
                value={this.state.repeatPassword}
                onBlur={this.isDisabled}
                validators={["isPasswordMatch", "required"]}
                errorMessages={["password mismatch", "this field is required"]}
                value={this.state.repeatPassword}
              />{" "} */}
              <Button
                type="submit"
                fullWidth
                variant="contained"
                color="primary"
                className={classes.submit}
              >
                Submit{" "}
              </Button>{" "}
            </ValidatorForm>{" "}
          </div>{" "}
        </Container>{" "}
      </div>
    );
  }
}

export default Signup;

Это моя регистрация, которая выглядит нормально, потому что токен остается в браузере, а пользователь хранится в Монго.

import React, { Component } from "react";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import Container from "@material-ui/core/Container";
import Link from "@material-ui/core/Link";
import Grid from "@material-ui/core/Grid";
import { ValidatorForm, TextValidator } from "react-material-ui-form-validator";
import { classes } from "../constants/login";
import axios from "axios";

export class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: "",
      errorText: ""
    };

    this.change = this.change.bind(this);
    this.submit = this.submit.bind(this);
  }

  change(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  submit(e) {
    e.preventDefault();
    axios
      .get("http://localhost:3000/api/users/current", {
        user: {
          email: this.state.email,
          password: this.state.password
        }
      })
      .then(res => {
        localStorage.setItem("cool-jwt", res.data.user.token);
        console.log(res.data.user.token);
      });
  }

  render() {
    return (
      <div>
        <Container component="main" maxWidth="xs">
          <CssBaseline />
          <div className={classes.paper}>
            <Avatar
              alt="IPCA"
              src="http://i68.tinypic.com/2gspvkm.png"
              className={classes.bigAvatar}
            />{" "}
            <Typography component="h1" variant="h5">
              Sign in
            </Typography>{" "}
            <ValidatorForm
              ref="form"
              className={classes.form}
              noValidate
              onSubmit={e => this.submit(e)}
            >
              <TextValidator
                variant="outlined"
                margin="normal"
                required
                fullWidth
                id="email"
                label="Email Address"
                name="email"
                autoComplete="email"
                autoFocus
                onChange={e => this.change(e)}
                value={this.state.email}
                validators={["required"]}
                errorMessages={["this field is required"]}
              />{" "}
              <TextValidator
                variant="outlined"
                margin="normal"
                required
                fullWidth
                name="password"
                label="Password"
                type="password"
                id="password"
                autoComplete="current-password"
                onChange={e => this.change(e)}
                value={this.state.password}
                onBlur={this.isDisabled}
                validators={["required"]}
                errorMessages={["this field is required"]}
              />{" "}
              <Button
                type="submit"
                fullWidth
                variant="contained"
                color="primary"
                className={classes.submit}
              >
                Submit{" "}
              </Button>{" "}
              <Grid container>
                <Grid item xs>
                  <Link href="#" variant="body2">
                    Forgot password?
                  </Link>
                </Grid>
                <Grid item>
                  <Link href="#" variant="body2">
                    {"Don't have an account? Sign Up"}
                  </Link>
                </Grid>
              </Grid>
            </ValidatorForm>{" "}
          </div>{" "}
        </Container>{" "}
      </div>
    );
  }
}

export default Login;

При входе на эту конечную точку я получаю

Это трюк Форма входа, которая мне не дает с ошибкой

GET /api/users/current 401 0.995 ms - 139
UnauthorizedError: No authorization token was found

Заранее спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...