使用Magic Links对React应用程序进行身份验证

2020年12月30日11:05:04 发表评论 31 次浏览

本文概述

安全性是任何Web应用程序中的一项基本功能, 可以防止未经授权的入侵和数据盗窃。保护应用程序安全的一种方法是通过身份验证。身份验证有助于控制用户对应用程序各部分的访问, 并确定用户的身份。

React应用程序的身份验证策略包括:

  • 密码
  • 两因素验证(2FA)
  • 验证码
  • 代币
  • 单点登录(SSO)

在本教程中, 我们将逐步完成:

  • 使用React设置基本身份验证流程
  • 控制对应用程序特定部分的访问
  • 魔术链接背后的想法
  • 将Magic Links集成到React应用程序中

什么是魔术链接?

魔术链接提供了一种无需密码即可验证用户身份的方法。由开发Fortmatic, 魔术链接是每当用户注册或登录应用程序时, 魔术SDK都会生成的链接。

用户注册或登录时, 将发生以下情况。

  1. 魔术链接已生成并发送到用户的电子邮件地址
  2. 用户单击链接, Magic对该用户进行身份验证
  3. 如果成功, 则将用户重定向回原始身份验证点;如果不成功, 则显示错误页面

为什么使用魔术链接?

对于用户而言, Magic Links消除了设置和记住安全密码的麻烦。它还使你不必在数据库中存储和管理用户密码和会话。它使用类似于SSH的基于区块链的密钥管理系统, 因此, 每当用户注册或登录时, 它都会生成一个公钥-私钥对, 随后将用于验证用户的请求。

先决条件

要继续学习本教程, 你需要具备以下条件。

  • npm> = v5.2或yarn
  • React和JavaScript的知识
  • 代码编辑器
  • 一种魔法帐户

创建一个React应用程序

首先, 我们必须创建一个新的React项目。打开你的终端, 然后运行:

npx create-react-app react-magic-tutorial

这将在魔术教程目录。要运行该应用程序, 请转到目录的根目录, 然后通过运行以下命令启动该应用程序。

cd react-magic-tutorial
npm start

设置魔术

在为React应用程序创建组件之前, 我们需要设置Magic服务。

我们为制作了一个自定义演示.
不完全是。点击这里查看.

使用Magic Links对React应用程序进行身份验证1

登录到魔法, 获取你的测试可发布API密钥以访问魔术服务, 然后将其复制。创建一个.env应用程序根目录中的文件, 在编辑器中打开文件并粘贴以下内容。

REACT_APP_PK_KEY=API_KEY

更换API_KEY使用复制的密钥, 然后返回到终端并安装Magic SDK。

npm install --save magic-sdk

接下来, 创建一个文件以处理Magic服务:

mkdir service
cd service
touch magic.js

这创建了一个magic.js服务目录中的文件。在编辑器中打开文件, 然后粘贴以下内容。

import { Magic } from 'magic-sdk';
const magic = new Magic(process.env.REACT_APP_PK_KEY);

export const checkUser = async (cb) => {
  const isLoggedIn = await magic.user.isLoggedIn();
  if (isLoggedIn) {
    const user = await magic.user.getMetadata();
    return cb({ isLoggedIn: true, email: user.email });
  }
  return cb({ isLoggedIn: false });
};

export const loginUser = async (email) => {
  await magic.auth.loginWithMagicLink({ email });
};

export const logoutUser = async () => {
  await magic.user.logout();
};

的魔法变量使用你的可发布变量初始化魔术服务API_KEY。的checkUser函数接受回调cb作为参数, 并检查用户是否已登录。如果用户已登录, 它将获取用户元数据并将其传递给回调函数。如果用户未登录, 则返回带有以下内容的回调函数:isLoggedIn属性设置为false。

的loginUser函数将用户电子邮件作为参数并将其传递给magic.auth.loginWithMagicLink({电子邮件})功能。此功能负责创建登录链接并将其发送给用户, 并创建用户会话。的注销用户函数注销用户并破坏会话。

构建React组件

下一步是创建应用程序所需的组件:

  1. 认证—一种表单组件, 允许用户注册或登录
  2. 仪表板—显示身份验证是否成功的组件
  3. 私人路线—包装器组件, 用于在呈现组件之前检查用户是否已通过身份验证;否则, 它将用户重定向回注册/登录页面
  4. 应用程式—主要应用程序组件。它呈现认证方式组件(如果用户未登录或仪表板组件(如果用户已登录)。

稍后我们将使用React Contexts根据用户是否通过身份验证将用户数据传递给呈现的组件。我们还将使用反应路由器处理路由。

要安装React Router, 请运行以下命令。

npm install react-router-dom

安装后, 运行以下命令。

cd src
mkdir components
cd components
touch Authenticate.js DashBoard.js PrivateRoute.js

这将创建一个组件目录, 其中的组件位于src目录。你的文件夹结构应类似于以下屏幕截图。

资料夹结构

我们将使用React Bootstrap库对项目进行样式设置。运行以下命令以安装该库。

npm install react-bootstrap bootstrap

打开Authtentication.js文件夹并粘贴以下内容。

import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import {
  Button, Form, FormGroup, FormLabel, FormControl, } from 'react-bootstrap';
import { loginUser } from '../services/magic';
const Authenticate = () => {
  const [email, setEmail] = useState('');
  const [loading, setLoading] = useState('');
  const [error, setError] = useState(null);
  const history = useHistory();
  const handleSubmit = async (event) => {
    event.preventDefault();
    setLoading(true);
    if (!email) {
      setLoading(false);
      setError('Email is Invalid');
      return;
    }
    try {
      await loginUser(email);
      setLoading(false);
      history.replace('/dashboard');
    } catch (error) {
      setError('Unable to log in');
      console.error(error);
    }
  };
  const handleChange = (event) => {
    setEmail(event.target.value);
  };
  return (
    <div className="w-50 p-5 mt-5 mx-auto">
      <h1 className="h1 text-center">React Magic Form</h1>
      <Form onSubmit={handleSubmit} className="p-2 my-5 mx-auto">
        <FormGroup className="mt-3" controlId="formBasicEmail">
          <FormLabel fontSize="sm">Enter Email Address</FormLabel>
          <FormControl
            type="email"
            name="email"
            id="email"
            value={email}
            onChange={handleChange}
            placeholder="Email Address"
          />
          <p className="text-danger text-small">{error}</p>
        </FormGroup>
        <Button
          type="submit"
          size="md"
          className="d-block w-100"
          variant="primary"
        >
          {loading ? 'Loading...' : 'Send'}
        </Button>
      </Form>
    </div>
  );
};
export default Authenticate;

该组件创建一个表单, 该表单具有用于电子邮件地址的文本字段和用于将Magic链接发送到用户输入的电子邮件的按钮。当用户单击按钮时, 它将运行handleSubmit函数, 用于验证电子邮件地址并调用loginUser从功能magic.js服务文件。

验证组件

我们要解决的下一个组件是仪表板零件。但首先, 让我们创建一个用户上下文, 将用户数据传递给我们仪表板零件。在里面src目录, 运行以下命令。

mkdir context
cd context
touch userContext.js

这创建了一个userContext上下文目录中的文件。打开文件并输入以下内容。

import { createContext } from 'react';
export const UserContext = createContext({ user: null });

的UserContext创建一个上下文并将user属性默认设置为null。要了解有关上下文以及如何有效使用上下文的更多信息, 请阅读React的上下文文档.

打开Dashboard.js组件文件并输入以下内容。

import React, { useContext } from 'react';
import { useHistory } from 'react-router-dom';
import Button from 'react-bootstrap/Button';
import { UserContext } from '../context/UserContext';
import { logoutUser } from '../services/magic';
const Dashboard = () => {
  const { email } = useContext(UserContext);
  const history = useHistory();
  const handleLogOut = async () => {
    try {
      await logoutUser();
      history.replace('/');
    } catch (error) {
      console.error(error);
    }
  };
  return (
    <div className="p-2">
      <div className="d-flex justify-content-end">
        <Button variant="primary" onClick={handleLogOut}>
          Sign Out
        </Button>
      </div>
      <h1 className="h1">User: {email}</h1>
    </div>
  );
};
export default Dashboard;

仪表板组件显示已登录的用户电子邮件和退出按钮。从上下文中获取登录用户UserContext;我们使用useContext钩子从中获取我们需要的数据UserContext.

当用户单击"退出"按钮时, 它将调用handleLogOut功能。的handleLogOut函数调用注销用户Magic服务提供的功能, 该服务负责销毁用户会话并注销用户。

完成此操作后, 我们使用重定向用户到注册页面。使用历史的钩反应路由器域包。的使用历史钩子使我们能够访问用户的会话历史记录, 并允许我们将用户重定向到历史记录中的某个点。

用户电子邮件和退出按钮

接下来, 我们创建私人路线零件。的私人路线组件允许我们为应用程序创建受保护的路由, 即用户只有在登录后才能访问的路由, 例如仪表板。

打开PrivateRoute.js文件并输入以下内容。

import React, { useContext } from 'react';
import { Redirect, Route } from 'react-router-dom';
import { UserContext } from '../context/UserContext';
const PrivateRoute = ({ component: Component, ...rest }) => {
  const { isLoggedIn } = useContext(UserContext);
  return (
    <Route
      {...rest}
      render={(props) =>
        isLoggedIn ? <Component {...props} /> : <Redirect to="/" />
      }
    />
  );
};
export default PrivateRoute;

的私人路线是包装的路线的组成部分反应路由器域。它检查用户的登录状态, isLoggedIn, 这是从UserContext。如果登录状态为true, 则呈现零件支柱。如果没有, 我们使用另一个反应路由器域组件称为重新导向, 它将用户重定向到一个位置, 在这种情况下为身份验证页面。

完成所有这些步骤后, 我们将所有内容汇总到一起应用程式零件。打开App.js根目录中的组件, 然后输入以下内容。

import React, { useState, useEffect } from 'react';
import {
  Switch, BrowserRouter as Router, Route, Redirect, } from 'react-router-dom';
import Spinner from 'react-bootstrap/Spinner';
import { UserContext } from './context/UserContext';
import { checkUser } from './services/magic';
import Authenticate from './components/Authenticate';
import Dashboard from './components/Dashboard';
import PrivateRoute from './components/PrivateRoute';
const App = () => {
  const [user, setUser] = useState({ isLoggedIn: null, email: '' });
  const [loading, setLoading] = useState();
  useEffect(() => {
    const validateUser = async () => {
      setLoading(true);
      try {
        await checkUser(setUser);
        setLoading(false);
      } catch (error) {
        console.error(error);
      }
    };
    validateUser();
  }, [user.isLoggedIn]);
  if (loading) {
    return (
      <div
        className="d-flex justify-content-center align-items-center"
        style={{ height: '100vh' }}
      >
        <Spinner animation="border" />
      </div>
    );
  }
  return (
    <UserContext.Provider value={user}>
      <Router>
        {user.isLoggedIn && <Redirect to={{ pathname: '/dashboard' }} />}
        <Switch>
          <Route exact path="/" component={Authenticate} />
          <PrivateRoute path="/dashboard" component={Dashboard} />
        </Switch>
      </Router>
    </UserContext.Provider>
  );
};
export default App;

App组件中要注意的第一件事是useEffecthoo每当应用呈现或isLoggedIn用户状态的属性更改。的validateUser函数称为checkUserMagic服务的功能, 该功能检查用户是否已登录。它接受回调, 这是我们的setUser函数, 并根据返回的内容设置用户状态checkUser功能。如果isLoggedIn属性为true, 然后将用户重定向到仪表板。我们使用UserContext.Provider将用户状态传递给应用程序的子组件。

我们的应用程序有两条路线:/路线, 该路线认证方式组件(我们的默认组件), 以及私人路线前面提到的包装路线组件, 它将仅呈现仪表板组件(如果用户已登录)。开关组件通过检查的路径来确保一次仅绘制一条路线路线零件。

现在我们的应用程序已准备就绪。启动它并测试身份验证流程。输入电子邮件地址后, 应将链接发送到你的电子邮件。当你单击链接时, 它将引导你返回到应用程序, 该应用程序在确认链接的有效性之后将你重定向到仪表板。

如果你玩完了就可以退出, 这将使你返回登录页面。

反应魔法形式

在本教程中, 我们逐步介绍了如何使用Magic Links保护你的React应用程序。 Magic服务提供的功能超出了本文的范围, 并支持与现有基础结构的集成。为了扩大你对Magic Links的了解, 建议你阅读官方文件.

在保护应用程序安全方面, 没有万能的。魔术可以替代你可能惯用的流行身份验证策略。

你可以找到我们构建的应用程序的存储库的GitHub.

全面了解生产React应用

调试React应用程序可能很困难, 尤其是当用户遇到难以重现的问题时。如果你有兴趣监视和跟踪Redux状态, 自动显示JavaScript错误以及跟踪缓慢的网络请求和组件加载时间,

尝试notlogy

.

使用Magic Links对React应用程序进行身份验证2
LogRocket仪表板免费试用横幅

日志火箭就像Web应用程序的DVR, 实际上记录了React应用程序中发生的一切。你可以汇总并报告问题发生时应用程序所处的状态, 而不用猜测为什么会发生问题。 notlogy还监视你的应用程序的性能, 并使用客户端CPU负载, 客户端内存使用情况等指标进行报告。

notlogy Redux中间件软件包在你的用户会话中增加了一层可见性。 notlogy记录Redux存储中的所有操作和状态。

现代化如何调试React应用程序-免费开始监控.

一盏木

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: