Итак, вот что я делаю. Когда пользователь входит в систему, токен JWT устанавливается в localStorage. Я пытаюсь сохранить логин пользователя. После входа в систему отображается кнопка выхода из системы в заголовке, но если я переосмыслил sh, я думаю, что хранилище избыточных данных очищено. Я прочитал несколько статей о том, как использовать проверку токена jwt в реакции и /me
маршрут или componentDidMount()
в приложении. js, но я не смог понять. Любая помощь будет оценена.
LoginForm.js
import React, { Component } from "react"
import validator from "validator"
import { loginUser } from "../actions/index"
import { connect } from "react-redux"
class LoginForm extends Component {
constructor(props) {
super(props)
this.state = {
email: "",
password: ""
}
}
handleChange = (event) => {
const { name, value } = event.target
this.setState({
[name]: value
})
}
handleSubmit = (event) => {
event.preventDefault();
const { email, password } = this.state;
const loginData = {
email: this.state.email,
password: this.state.password
}
if (!email || !password) {
return alert('Email and password are must.');
}
if (password.length < 6) {
return alert('Password must contain 6 characters.');
}
if (!validator.isEmail(email)) {
return alert('Invalid email.');
}
this.props.dispatch(loginUser(loginData))
this.props.history.push("/")
}
render() {
const isAuthInProgress = this.props.auth.isAuthInProgress
return (
<div>
<div className="field">
<p className="control has-icons-left has-icons-right">
<input className="input" onChange={this.handleChange} name="email" value={this.state.email} type="email" placeholder="Email" />
<span className="icon is-small is-left">
<i className="fas fa-envelope"></i>
</span>
<span className="icon is-small is-right">
<i className="fas fa-check"></i>
</span>
</p>
</div>
<div className="field">
<p className="control has-icons-left">
<input className="input" onChange={this.handleChange} name="password" value={this.state.password} type="password" placeholder="Password" />
<span className="icon is-small is-left">
<i className="fas fa-lock"></i>
</span>
</p>
<p className="has-text-danger">Forgot password?</p>
</div>
<div className="field">
<p className="control">
{
isAuthInProgress ? <p>Logging in...</p>
:
<button onClick={this.handleSubmit} className="button is-success">
Login
</button>
}
</p>
</div>
</div >
)
}
}
const mapStateToProps = (state) => {
return state
}
export default connect(mapStateToProps)(LoginForm)
actions/index.js
import axios from "axios"
export const registerUser = (registrationData) => {
console.log("inside register action")
return async dispatch => {
dispatch({ type: "REGISTRATION_STARTS" })
try {
const res = await axios.post("http://localhost:3000/api/v1/users/register", registrationData)
dispatch({
type: "REGISTRATION_SUCCESS",
data: { user: res.data },
})
} catch (err) {
dispatch({
type: "REGISTRATION_ERROR",
data: { error: "Something went wrong" }
})
}
}
}
export const loginUser = (loginData) => {
console.log("inside login action")
return async dispatch => {
dispatch({ type: "AUTH_STARTS" })
try {
const res = await axios.post("http://localhost:3000/api/v1/users/login", loginData)
dispatch({
type: "AUTH_SUCCESS",
data: { user: res.data }
})
localStorage.setItem("authToken", res.data.token)
} catch (err) {
dispatch({
type: "AUTH_ERROR",
data: { error: "Something went wrong" }
})
}
}
}
routes/users.js
router.post("/register", userController.registerUser)
router.post("/login", userController.loginUser)
router.get("/:userId", userController.getUser)
router.get("/list", userController.listUsers)
userController.js
const User = require("../models/User")
const auth = require("../utils/auth")
const validator = require("validator")
module.exports = {
registerUser: (req, res, next) => {
const { username, email, password } = req.body
User.create(req.body, (err, createdUser) => {
if (err) {
return next(err)
} else if (!username || !email || !password) {
return res.status(400).json({ message: "Username, email and password are must" })
} else if (!validator.isEmail(email)) {
return res.status(400).json({ message: "Invaid email" })
} else if (password.length < 6) {
return res.status(400).json({ message: "Password should be of at least 6 characters" })
}
else {
return res.status(200).json({ user: createdUser })
}
})
},
loginUser: (req, res, next) => {
const { email, password } = req.body
if (!email || !password) {
return res.status(400).json({message: "Email and password are must"})
}
User.findOne({ email }, (err, user) => {
if (err) {
return next(err)
} else if (!validator.isEmail(email)) {
return res.status(400).json({ message: "Invalid email" })
} else if (!user) {
return res.status(402).json({ error: "User not found" })
} else if (!user.confirmPassword(password)) {
return res.status(402).json({ error: "Incorrect password" })
}
// generate token here
const token = auth.signToken(email)
res.status(200).json({ user, token })
})
},
getUser: (req, res, next) => {
User.findById(req.params.userId, (err, user) => {
if (err) {
return next(err)
} else if (!user) {
return res.status(404).json({ message: "User not found" })
} else {
return res.status(200).json({ user: user })
}
})
},
listUsers: (req, res) => {
User.find({}, (err, users) => {
if (err) {
return res.status(404).json({ error: "No users found" })
} else {
return res.status(200).json({ user: user })
}
})
}
}
utils/auth.js
const jwt = require("jsonwebtoken")
function signToken(payload) {
return jwt.sign(payload, process.env.JWTSECRET)
}
function verifyToken(req, res, next) {
const token = req.headers.Authorization || req.headers.authorization || ""
if (!token) {
return res.status(403).json({ error: "Not authorized"})
}
jwt.verify(token, process.env.JWTSECRET, (err, decoded) => {
if (err) {
return res.status(403).json({ error: "Not authorized" })
}
req.user = decoded
next()
})
}
module.exports = { signToken, verifyToken }