我目前正在使用带有Passport.js的MERN堆栈进行身份验证的应用程序,特别是Google OAuth2策略。我当前的应用程序具有简单的登录功能,该功能可以从客户端重定向到Google同意页面,然后再重定向到服务器的重定向URL,然后应将其重定向到客户端的主应用程序。我很确定这就是您需要在服务器端进行的所有操作,现在我对如何在React Router端处理此问题感到有些困惑。
因此,首先,我在“公开路线”中有我的Google登录按钮,然后点击了触发Google OAuth的服务器中的端点
class Public extends Component {
render() {
return (
<div>
<h1>Public Route</h1>
<a href="http://localhost:5000/api/auth/google">Sign In</a>
</div>
)
}
}
服务器从 localhost:5000 / auth / google / redirect 重定向到 localhost:3000 / protected 后>,我相信它可以追溯到触发React路由器的App.js
class App extends Component {
constructor(props) {
super(props)
this.state = { authenticated: false }
}
componentDidMount() {
api.get('/auth/user').then(({data}) => {
if (data) this.setState({authenticated: true})
}).catch((err) => console.error(err))
}
render() {
const { authenticated } = this.state
return (
<div className="App">
<Switch>
<Route exact path='/' component={Public} />
<PrivateRoute exact authed={authenticated} path='/app' component={Protected} />
</Switch>
</div>
)
}
}
这就是事情变得有些混乱的地方。因此,我认为它将首先在componentDidMount()之前呈现,因此 authenticated 状态仍然为false,因此PrivateRoute将客户端重定向回 localhost:3000 / 并渲染公共路线。然后,执行所有操作,最后运行componentDidMount()并最终获取用户,现在 authenticated 为true,但是现在太晚了,因为客户端已经重定向到 localhost:3000 / ,因此它不会再访问PrivateRoute。
这是我的PrivateRoute组件,以防有人怀疑:
const PrivateRoute = ({ component: Component, authed, ...rest }) => (
<Route { ...rest} render={(props) => authed ?
<Component {...props} /> :
<Redirect to={{pathname: '/'}} />
} />
)
我到目前为止所做的事情:
谢谢!
答案 0 :(得分:0)
我认为,在您的privateRoute组件本身中进行身份验证检查会比在App和privateRoute上拆分要容易得多。
无论如何,您可以呈现“加载屏幕”组件,该组件仍会阻止他们到达受保护的路由,而不是在未通过身份验证时重定向。这样,您可以等待http请求返回,然后再最终决定是否允许用户访问或将其重定向回登录页面。这是一个示例:
const PrivateRoute = ({ component: Component, ...rest }) => {
const [isAuthenticated, setAuthenticated] = useState(false);
useEffect(() => {
axiosInstance.get('/auth/isauthenticated').then(({ data: { user } }) => {
if (user) {
setAuthenticated(true);
} else {
window.location = '/menu/login';
}
});
}, []);
return (isAuthenticated
? <Route {...rest} render={(props) => <Component {...props} />} />
: <p>{'Loading'}</p>;)
}