Reactjs 使用AWS的受保护路由使用React上下文进行放大

Reactjs 使用AWS的受保护路由使用React上下文进行放大,reactjs,amazon-web-services,aws-amplify,react-context,Reactjs,Amazon Web Services,Aws Amplify,React Context,我正在将一个应用程序从Firebase迁移到AWS Amplify。我想创建一个React上下文,如果用户未登录,它将提供路由保护 例如,我的Auth.js文件: import React, { useEffect, useState, createContext } from 'react' import fire from './firebase' export const AuthContext = createContext() export const AuthProvider =

我正在将一个应用程序从Firebase迁移到AWS Amplify。我想创建一个React上下文,如果用户未登录,它将提供路由保护

例如,我的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>
    )
}
import React,{useffect,useState,createContext}来自“React”
从“/firebase”导入火
export const AuthContext=createContext()
导出常量AuthProvider=({children})=>{
常量[currentUser,setCurrentUser]=useState(null)
useffect(()=>{
fire.auth().onAuthStateChanged(setCurrentUser)
}, [])
返回(
{儿童}
)
}
和我的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
import*作为来自“React”的React
从“react router dom”导入{BrowserRouter,Switch,Route}
从“./components/Navbar/Navbar”导入导航栏
从“./routes/Home”导入主页
从“./routes/Register”导入寄存器
从“./components/Footer/Footer”导入页脚
从“./components/notification/NotificationProvider”导入AlertProvider
从“./components/notification/notification”导入MyAlert
从“/Auth”导入{AuthProvider}
从“/PrivateRoute”导入PrivateRoute
常量应用=()=>{
返回(
忘记密码}
/>
)
}
导出默认应用程序
这一切都很好

我如何使用AWS Amplify做类似的事情?基本上,我将如何创建一个Auth.js文件,该文件将环绕我的路由,并为它们提供一个用户上下文(当用户的身份验证状态更改时,该上下文将更新)


谢谢

您可以通过设置自定义的
protectedRoute
HOC来实现这一点,该HOC将用于保护任何需要身份验证的路由。它将检查用户是否已登录,如果用户未登录,则会将其重新定向到指定的路由

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
您还可以使用来自aws amplify的预先构建的名为
的HOC with Authenticator
,它提供用户界面并检查用户身份验证状态

配置文件页面的示例用例:

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)
import React,{useState,useffect}来自“React”
从“antd”导入{Button}
从“aws放大”导入{Auth}
从“aws放大反应”导入{withAuthenticator}
从“./Container”导入容器
函数配置文件(){
useffect(()=>{
checkUser()
}, [])
const[user,setUser]=useState({})
异步函数checkUser(){
试一试{
const data=await Auth.currentUserPoolUser()
const userInfo={username:data.username,…data.attributes,}
setUser(userInfo)
}catch(err){console.log('error:',err)}
}
函数签出(){
Auth.signOut()
.catch(err=>console.log('error signing out:',err'))
}
返回(
轮廓
用户名:{user.Username}
电子邮件:{user.Email}
电话:{user.Phone_number}
退出
);
}
使用验证器导出默认值(配置文件)
两者的路径相同,下面我链接了一个我用于两者的示例:

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
import React,{useState,useffect}来自“React”
从“react router dom”导入{HashRouter,Switch,Route}
从“./Nav”导入导航
从“./Public”导入公共
从“./Profile”导入配置文件
从“./Protected”导入受保护的
常数路由器=()=>{
const[current,setCurrent]=useState('home')
useffect(()=>{
setRoute()
window.addEventListener('hashchange',setRoute)
return()=>window.removeEventListener('hashchange',setRoute)
}, [])
函数setRoute(){
const location=window.location.href.split(“/”)
常量路径名=位置[location.length-1]
setCurrent(路径名?路径名:'home')
}
返回(
)
}
导出默认路由器

也许不需要使用上下文,相反,您可以使用一个HOC组件来包装受保护的路由,并检查用户是否从那里经过身份验证,然后允许他们使用路由,或者如果不允许他们重定向到指定的路径。谢谢,您是否有到代码示例的链接?我是新来的,一定会很感激一些我能消化的代码。谢谢!这是一个很好的回应,让梅格拉德更清楚它帮助了你@yudhiesh,我不理解的是你的checkAuthState函数。只有在身份验证失败时,您才会发送到配置文件。当它经过的时候,你不应该送它去某条路线吗?
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