Server-Side Auth Flow with React Router

2019-04-10 22:22发布

I was wondering how to exactly implement authentication flow with React Router if my app is rendering server-side?

The scenario:

When the user first arrives at the app, we invoke an onEnter router method in order to check if any current user is present (localStorage), if they are we will redirect them to their dashboard, otherwise we redirect them to the landing page.

Therefore when my app hits my protected routes onEnter, here's ideally what should happen:

onEnter: () => {
    if (localStorage.getItem('authToken')) {
        // Authenticate and redirect user to intended path
    } else {
        // Redirect the user to the login page
    }
}

The problem here is that because we're rendering server-side, we don't have access to things such as localStorage. Can anyone suggest a way to overcome this, or a better way to handle server-side auth with React Router?

1条回答
男人必须洒脱
2楼-- · 2019-04-10 22:31

You could use context, e.g:

import React, { Component, PropTypes, Children } from 'react'

class Provider extends Component {

    static childContextTypes = {
        isAuthed: PropTypes.bool
    }

    constructor(props) {
        super(props);
        this.initialData = isClient ? window.__initialData__ : props.initialData;
    }

    getChildContext() {
        return {
            isAuthed: this.initialData.isAuthed
        };
    }

    render() {
        let { children } = this.props;
        return Children.only(children);
    }
}

And wrap:

// The server creates this object:
const initialData = {
    isAuthed: true
};

if (IS_CLIENT) {
    ReactDOM.render(
        <Provider>
            <Router history={createHistory()}>{Routes}</Router>
        </Provider>,
        document.getElementById('app')
    );
}

if (IS_SERVER) {
    // Using renderToStaticMarkup/renderToString etc on:
    <Provider initialData={initialData}> 
        <RoutingContext {...renderProps} />
    </Provider>
}

You can then access it on the server or client from any component:

import React, { Component, PropTypes } from 'react'

class SomeComponent extends Component {

    static contextTypes = {
        isAuthed: PropTypes.bool
    }

    constructor(props, context) {
        super(props, context);

        console.log(context.isAuthed); // this.context outside ctor
    }
}

Simple client check something like typeof document !== 'undefined'

查看更多
登录 后发表回答