React&Redux、ExpressバックエンドアプリでJWTを使用し、redux-persistなどのパッケージを使用せずにユーザーログインを永続化するにはどうすればよいですか?

metalHeadDev

だから、これが私がしていることです。ユーザーがログインすると、JWTトークンがlocalStorageに設定されます。ユーザーログインを維持しようとしています。ログイン後、ヘッダーにログアウトボタンが表示されますが、更新すると、reduxストアがクリアされたと思います。私が使用する方法についていくつかの記事を読むJWTトークンの検証で反応し、/meルートまたはcomponentDidMount()App.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 }
C.ゴチェフ

クッキーを使うのが一番いい方法だと思います。

ログインルートにCookieを設定します

    res.cookie("authToken", auth.signToken(email), {
      httpOnly: false,
     })

そして、反応側では、js-cookieパッケージを使用してパッケージを取得し、後続の認証済みリクエストで使用できます

import Cookies from 'js-cookie';

class SomeComponent extends Component {

    constructor(props) {
        super(props)
        this.state = {
            email: "",
            password: "",
            cookie: Cookies.get('authToken')
        }
    }
 }

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ