我目前正在开发一个使用带有 Passport.js 的 MERN 堆栈进行身份验证的应用程序,特别是 Google OAuth2 策略。我当前的应用程序具有简单的登录功能,可以从客户端重定向到 Google 同意页面并返回到服务器的重定向 url,然后应该重定向到客户端的主应用程序。我很确定这就是你在服务器端需要做的所有事情,现在我对如何在 React Router 端处理这个有点困惑。
所以首先,我的公共路由中有我的谷歌登录按钮,然后点击服务器中触发谷歌 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() 之前先渲染,所以经过身份验证的状态仍然是 false,所以 PrivateRoute 将客户端重定向回 localhost :3000/并渲染公共路由。毕竟,运行 componentDidMount() 并最终获取用户并且现在身份验证是真的,但是现在为时已晚,因为客户端已经重定向到localhost:3000/所以它不再访问 PrivateRoute。
如果有人想知道,这是我的 PrivateRoute 组件:
const PrivateRoute = ({ component: Component, authed, ...rest }) => (
<Route { ...rest} render={(props) => authed ?
<Component {...props} /> :
<Redirect to={{pathname: '/'}} />
} />
)
到目前为止我所做的:
- 使用 componentWillMount() - 没有区别,而且我相信这很快就会被弃用
- 使用具有isAuthenticated、login()和logout()成员的全局身份验证对象。我在我的公共组件中创建了该对象的一个实例,并添加了onClick={auth.login}以及 href。但是,onClick 在 href 浏览器重定向之前首先运行,因此它会首先尝试获取用户(即使还没有任何设置),所以isAuthenticated不会设置为 true
提前致谢!