如何使用redux and node.js保护react.js app auth
#教程 #react #redux #node

在本教程中,我们将学习如何确保用redux and node.js

进行react.js应用程序中的安全性。

在现代网络开发中,实施安全身份验证对于保护敏感用户信息并防止未经授权访问至关重要。本文将指导您完成react.js身份验证的过程。

使用Node.js设置后端并Express:

  1. 首先使用NPM或YARN等软件包管理器设置Node.js项目。
  2. 安装所需的依赖项,例如express,bcrypt密码哈希和用于生成和验证jwts的jsonwebtoken(json web令牌)。
  3. 创建用于用户注册,登录和注销的路由。
  4. 实现中间件,以验证受保护路线上的JWT,以确保只有身份验证的用户才能访问它们。
  5. 将用户信息牢固地存储在数据库中,以确保密码得到正确的哈希和腌制。

const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

const mongoose = require('mongoose');

const Admin = mongoose.model('Admin');

require('dotenv').config({ path: '.variables.env' });

exports.login = async (req, res) => {
  try {
    const { email, password } = req.body;

    // validate
    if (!email || !password)
      return res.status(400).json({
        success: false,
        result: null,
        message: 'Not all fields have been entered.',
      });

    const admin = await Admin.findOne({ email: email, removed: false });

    if (!admin)
      return res.status(400).json({
        success: false,
        result: null,
        message: 'No account with this email has been registered.',
      });

    const isMatch = await bcrypt.compare(password, admin.password);
    if (!isMatch)
      return res.status(400).json({
        success: false,
        result: null,
        message: 'Invalid credentials.',
      });

    const token = jwt.sign(
      {
        id: admin._id,
      },
      process.env.JWT_SECRET,
      { expiresIn: req.body.remember ? 365 * 24 + 'h' : '24h' }
    );

    const result = await Admin.findOneAndUpdate(
      { _id: admin._id },
      { isLoggedIn: true },
      {
        new: true,
      }
    ).exec();

    res
      .status(200)
      .cookie('token', token, {
        maxAge: req.body.remember ? 365 * 24 * 60 * 60 * 1000 : null, // Cookie expires after 30 days
        sameSite: 'Lax',
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production' ? true : false,
        domain: req.hostname,
        Path: '/',
      })
      .json({
        success: true,
        result: {
          token,
          admin: {
            id: result._id,
            name: result.name,
            isLoggedIn: result.isLoggedIn,
          },
        },
        message: 'Successfully login admin',
      });
  } catch (err) {
    res.status(500).json({ success: false, result: null, message: err.message, error: err });
  }
};

exports.isValidAdminToken = async (req, res, next) => {
  try {
    const token = req.cookies.token;

    if (!token)
      return res.status(401).json({
        success: false,
        result: null,
        message: 'No authentication token, authorization denied.',
        jwtExpired: true,
      });

    const verified = jwt.verify(token, process.env.JWT_SECRET);

    if (!verified)
      return res.status(401).json({
        success: false,
        result: null,
        message: 'Token verification failed, authorization denied.',
        jwtExpired: true,
      });

    const admin = await Admin.findOne({ _id: verified.id, removed: false });
    if (!admin)
      return res.status(401).json({
        success: false,
        result: null,
        message: "Admin doens't Exist, authorization denied.",
        jwtExpired: true,
      });

    else {
      req.admin = admin;
      next();
    }
  } catch (err) {
    res.status(503).json({
      success: false,
      result: null,
      message: err.message,
      error: err,
    });
  }
};

在实际react.js node.js项目中找到所有代码源:

github repo:https://github.com/idurar/idurar-erp-crm

Open Source ERP / CRM

在前端实施用户注册和登录:

  1. 使用Create-React-App或任何其他首选方法设置React.js项目。
  2. 安装必要的依赖项,例如用于提出API请求的Axios,用于处理客户端路由的REACT-ROUTOR-DOM以及用于异步动作创建者的Redux-thunk。
  3. 创建注册表格,用户可以在其中提供其详细信息,例如用户名和密码。
  4. 在表单提交时,请派遣操作将用户数据发送到后端API进行注册。
  5. 实现带有用户名和密码字段的登录表单。
  6. 派遣操作以对后端API的用户凭证进行身份验证。
  7. 如果身份验证成功,请将从服务器收到的JWT存储在浏览器的cookie hollyhttp中以供将来的请求。

import { API_BASE_URL } from '@/config/serverApiConfig';

import axios from 'axios';
import errorHandler from '@/request/errorHandler';
import successHandler from '@/request/successHandler';

export const login = async ({ loginData }) => {
  try {
    const response = await fetch(API_BASE_URL + `login?timestamp=${new Date().getTime()}`, {
      method: 'POST', // *GET, POST, PUT, DELETE, etc.
      mode: 'cors', // no-cors, *cors, same-origin
      cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cache
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
      },
      redirect: 'follow', // manual, *follow, error
      referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      body: JSON.stringify(loginData), // body data type must match "Content-Type" header
    });

    const { status } = response;
    const data = await response.json();

    successHandler(
      { data, status },
      {
        notifyOnSuccess: false,
        notifyOnFailed: true,
      }
    );
    return data;
  } catch (error) {
    return errorHandler(error);
  }
};
export const logout = async () => {
  axios.defaults.withCredentials = true;
  try {
    window.localStorage.clear();
    await axios.post(API_BASE_URL + `logout?timestamp=${new Date().getTime()}`);
  } catch (error) {
    return errorHandler(error);
  }
};

为什么使用Redux来管理身份验证状态?

redux是一个可预测的状态容器,可帮助以一致且有条理的方式管理应用程序的全局状态。通过将身份验证状态集中在Redux中,我们可以轻松地同步不同组件的登录/注销状态并制作安全的API请求。

import * as actionTypes from './types';
import * as authService from '@/auth';

import history from '@/utils/history';

export const login =
  ({ loginData }) =>
  async (dispatch) => {
    dispatch({
      type: actionTypes.LOADING_REQUEST,
      payload: { loading: true },
    });
    const data = await authService.login({ loginData });

    if (data.success === true) {
      window.localStorage.setItem('isLoggedIn', true);
      window.localStorage.setItem('auth', JSON.stringify(data.result.admin));
      dispatch({
        type: actionTypes.LOGIN_SUCCESS,
        payload: data.result.admin,
      });
      history.push('/');
    } else {
      dispatch({
        type: actionTypes.FAILED_REQUEST,
        payload: data,
      });
    }
  };

export const logout = () => async (dispatch) => {
  authService.logout();
  dispatch({
    type: actionTypes.LOGOUT_SUCCESS,
  });
  history.push('/login');
};


使用JWT确保API请求:

  1. 在前端创建一个拦截器,将JWT令牌附加到每个API请求。
  2. 收到服务器的响应后,检查授权错误或已过期的令牌。
  3. 如果令牌已过期,请提示用户再次登录。
  4. 如果由于未经授权的访问而发生错误,请将用户重定向到登录页面。

在实际react.js node.js项目中找到所有代码源:

github repo:https://github.com/idurar/idurar-erp-crm

Open Source ERP / CRM

通过遵循以下步骤,您可以确保使用Redux进行状态管理和Node.js作为后端服务器中的React.js应用程序中的安全身份验证流。请记住,要始终实施最佳实践,以进行安全密码存储,令牌处理和API请求验证以保护用户信息并维护数据完整性。