【问题标题】:Using Passport Google OAuth2 to authenticate private React Routes使用 Passport Google OAuth2 验证私有 React 路由
【发布时间】:2020-07-03 20:23:00
【问题描述】:

我目前正在开发一个应用程序,使用带有 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 为真,但现在为时已晚,因为客户端已经重定向到 localhost:3000/ 所以它不再访问 PrivateRoute。

如果有人想知道,这是我的 PrivateRoute 组件:

const PrivateRoute = ({ component: Component, authed, ...rest }) => (
    <Route { ...rest} render={(props) => authed ? 
        <Component {...props} /> :
        <Redirect to={{pathname: '/'}} />
    } />
)

到目前为止我做了什么:

  • 使用 componentWillMount() - 没有区别,而且我相信这很快就会被弃用
  • 使用具有 isAuthenticatedlogin()logout() 成员的全局身份验证对象。我在我的公共组件中创建了该对象的一个​​实例,并添加了 onClick={auth.login} 以及 href。但是,onClick 在 href 浏览器重定向之前首先运行,因此它会首先尝试获取用户(即使还没有任何设置),因此 isAuthenticated 不会设置为 true

提前致谢!

【问题讨论】:

  • 我遇到了类似的问题。在 Google 成功验证身份后,您是否设法在 React 上设置 isAuthenticated:true

标签: reactjs authentication react-router passport-google-oauth


【解决方案1】:

我认为在您的 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>;)
}

【讨论】:

    猜你喜欢
    • 2018-02-28
    • 2018-05-19
    • 2015-03-24
    • 2020-06-02
    • 2022-08-12
    • 1970-01-01
    • 2022-01-17
    • 2016-01-18
    • 2017-01-08
    相关资源
    最近更新 更多