[英]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.