简体   繁体   English

使用 React 上下文的 AWS Amplify 保护路由

[英]Protected Routes with AWS Amplify using React context

I am migrating an app from Firebase to AWS Amplify.我正在将一个应用程序从 Firebase 迁移到 AWS Amplify。 I want to create a React context which will provide route protection if the user is not logged in.我想创建一个 React 上下文,如果用户未登录,它将提供路由保护。

For example, my Auth.js file:例如我的 Auth.js 文件:

import React, { useEffect, useState, createContext } from 'react'
import fire from './firebase'

export const AuthContext = createContext()

export const AuthProvider = ({ children }) => {
    const [currentUser, setCurrentUser] = useState(null)

    useEffect(() => {
        fire.auth().onAuthStateChanged(setCurrentUser)
    }, [])

    return (
        <AuthContext.Provider value={{ currentUser }}>
            {children}
        </AuthContext.Provider>
    )
}

And my App.js file:还有我的 App.js 文件:

import * as React from 'react'
import { BrowserRouter, Switch, Route } from 'react-router-dom'

import Navbar from './components/navbar/navbar'
import Home from './routes/Home'
import Register from './routes/Register'

import Footer from './components/footer/Footer'

import AlertProvider from './components/notification/NotificationProvider'
import MyAlert from './components/notification/Notification'

import { AuthProvider } from './Auth'
import PrivateRoute from './PrivateRoute'

const App = () => {
    return (
        <AuthProvider>
            <BrowserRouter>
                <AlertProvider>
                    <div className="app">
                        <Navbar />
                        <MyAlert />
                        <Switch>
                            <Route path="/" exact component={Home} />
                            <Route
                                path="/register"
                                exact
                                component={Register}
                            />
                            <Route
                                path="/forgot-password"
                                render={(props) => <div>Forgot Password</div>}
                            />
                            <Route path="*" exact={true} component={Home} />
                        </Switch>
                        <Footer />
                    </div>
                </AlertProvider>
            </BrowserRouter>
        </AuthProvider>
    )
}

export default App

This all works fine.这一切都很好。

How would I do something similar with AWS Amplify?我如何使用 AWS Amplify 执行类似的操作? Essentially how would I create a Auth.js file that would wrap around my routes and give them a user context (which would update when the authentication status for the user is changed).本质上,我将如何创建一个 Auth.js 文件来环绕我的路由并为它们提供用户上下文(当用户的身份验证状态更改时,该文件将更新)。

Thanks!谢谢!

You can achieve this by setting up a custom protectedRoute HOC that will be used to protect any route that requires authentication.您可以通过设置一个自定义的protectedRoute HOC 来实现这一点,该 HOC 将用于保护任何需要身份验证的路由。 It will check if the user is signed-in and if the user is not signed-in then it will re-direct them to a specified route.它将检查用户是否已登录,如果用户未登录,则会将他们重定向到指定的路线。

protectedRoute.js

import React, { useEffect } from 'react'
import { Auth } from 'aws-amplify'

const protectedRoute = (Comp, route = '/profile') => (props) => {
  async function checkAuthState() {
    try {
      await Auth.currentAuthenticatedUser()
    } catch (err) {
      props.history.push(route)
    }
  }
  useEffect(() => {
    checkAuthState()
  })
  return <Comp {...props} />
}

export default protectedRoute

You can specify the default route or another route like the following:您可以指定默认路由或其他路由,如下所示:

// default redirect route
export default protectedRoute(Profile)

// custom redirect route
export default protectedRoute(Profile, '/sign-in')

You could also use the pre-built HOC from aws-amplify called withAuthenticator and that provides the UI as well as checking the users authentication status.您还可以使用来自 aws-amplify 的预构建 HOC,称为withAuthenticator ,它提供 UI 以及检查用户身份验证状态。

Sample use case for a profile page:配置文件页面的示例用例:

import React, { useState, useEffect } from 'react'
import { Button } from 'antd'
import { Auth } from 'aws-amplify'
import { withAuthenticator } from 'aws-amplify-react'
import Container from './Container'

function Profile() {
  useEffect(() => {
    checkUser()
  }, [])
  const [user, setUser] = useState({}) 
  async function checkUser() {
    try {
      const data = await Auth.currentUserPoolUser()
      const userInfo = { username: data.username, ...data.attributes, }
      setUser(userInfo)
    } catch (err) { console.log('error: ', err) }
  }
  function signOut() {
    Auth.signOut()
      .catch(err => console.log('error signing out: ', err))
  }
  return (
    <Container>
      <h1>Profile</h1>
      <h2>Username: {user.username}</h2>
      <h3>Email: {user.email}</h3>
      <h4>Phone: {user.phone_number}</h4>
      <Button onClick={signOut}>Sign Out</Button>
    </Container>
  );
}

export default withAuthenticator(Profile)

The routing for both would be the same and below I have linked a sample that I have used for both.:两者的路由是相同的,下面我链接了一个我用于两者的示例。:

import React, { useState, useEffect } from 'react'
import { HashRouter, Switch, Route } from 'react-router-dom'

import Nav from './Nav'
import Public from './Public'
import Profile from './Profile'
import Protected from './Protected'

const Router = () => {
  const [current, setCurrent] = useState('home')
  useEffect(() => {
    setRoute()
    window.addEventListener('hashchange', setRoute)
    return () =>  window.removeEventListener('hashchange', setRoute)
  }, [])
  function setRoute() {
    const location = window.location.href.split('/')
    const pathname = location[location.length-1]
    setCurrent(pathname ? pathname : 'home')
  }
  return (
    <HashRouter>
      <Nav current={current} />
      <Switch>
        <Route exact path="/" component={Public}/>
        <Route exact path="/protected" component={Protected} />
        <Route exact path="/profile" component={Profile}/>
        <Route component={Public}/>
      </Switch>
    </HashRouter>
  )
}

export default Router

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 firebase 在 React 中保护路由 - Protected routes in React using firebase 将 api 网关与 aws cognito 一起用于受保护的路由 - using api gateway with aws cognito for protected routes 为什么在使用 React Router V6 保护路由时,我使用 AWS Amplify 的 React Authentication 组件会被无限渲染 - Why is my React Authentication component using AWS Amplify being rendered infinitely when using React Router V6 to protect routes Cognito + Google + React - 注销无法使用 aws amplify - Cognito + Google + React - signout not working using aws amplify 使用 Basic React App 时无法在 AWS Amplify 中使用图像 - Cannot use images in AWS Amplify when using Basic React App 如何使用 AWS Amplify 和 React 在注册后让用户登录 - How to sign user in after registration using AWS Amplify and React AWS Amplify S3 受保护文件 - Lambda Function 调用 - AWS Amplify S3 Protected File - Lambda Function Invocation 在 AWS Amplify 上构建 React 应用程序在 Amplify 控制台中失败 - Build of React application on AWS Amplify fails in Amplify Console aws cognito 谷歌社交登录使用没有托管 ui 且没有放大的反应 - aws cognito google social login using react without hosted ui and without amplify 在 React Native 上自定义 AWS amplify withAuthenticator UI - Customize AWS amplify withAuthenticator UI on React Native
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM