使用Passport Google OAuth2验证专用的React路由

时间:2020-03-23 11:11:31

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

我目前正在使用带有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: '/'}} />
    } />
)

我到目前为止所做的事情:

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

谢谢!

1 个答案:

答案 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>;)
}