通过重定向将数据从Express发送到React

4
我有两个应用程序已链接:一个作为服务器(express)在端口5000上,另一个作为客户端(React)在端口3000上。我想从服务器向客户端发送数据--到特定页面。
流程:
1. 用户在localhost:3000上点击'登录' 2. 他们被重定向到返回代码并重定向到localhost:5000/api/callback的外部站点 3. router.get('/api/callback') 根据代码获取授权令牌然后重定向到localhost:3000/dashboard(通过React Router显示Dashboard组件) 4. 仪表板通过从服务器抓取Token来将其保存在其状态中 5. 然后,仪表板将调用服务器以根据Token获取其他数据
我意识到这很复杂,但基本上这就是我的问题所在; 我不完全明白如何使Express和React正确通信。
在server.js中:
router.get('/callback', async (req, res) => {
    const code = req.query.code;
    const token = await getAuthorizationTokenFromExternalSite(code);

    // Poor attempt to persist data
    res.cookie('token', token);

    // Poor attempt to let the user see this URL
    res.redirect("http://localhost:3000/dashboard");
});

router.get('/dashboard', (req, res) => {
    res.send({ token: req.cookies['token'] });
});

client/src/App.js

class App extends Component {

    render() {
        return(
            <BrowserRouter>
                <div>
                    <Route exact path="/" component={LoginPage} />
                    <Route path="/dashboard" component={Dashboard} />
                </div>
            </BrowserRouter>
        );
    }

}

export default App;

client/src/Dashboard.js

class Dashboard extends Component {

    state = { token: null };

    componentDidMount() {
        fetch('/api/dashboard')
          .then(res => this.setState({ token: res.token }));
    }

    render() {
        return(
            <div>
                Tis the Dashboard, the token is {this.state.token}.
            </div>
        );
    }

}

export default Dashboard;

如何正确地将用户从服务器带回 localhost:3000,然后传递必要的数据?

1个回答

5
我认为将此令牌放入重定向用户到UI的URI的#<token here>部分的哈希中是相当普遍的。 URI的#部分不会发送到您重定向到的后端服务器,因此比仅将其放在?后面要好一些。然后,您可以(在UI中)解析该令牌并使用它发起请求,通常通过传递HTTP头Authorization: Bearer ${token}
如果将其放在Cookie中,可以接受,如果它是http-only(这意味着UI无法以编程方式访问它),并且后端知道要查看Cookie以获取令牌。长期而言,这比仅通过URL将访问令牌传递给UI更复杂(我认为)。
审查身份验证流/动态;以防证明有帮助:
- 用户打开页面 - 单击登录,被重定向到登录提供商门户网站,或者弹出窗口显示 - 用户输入数据并将其提交给后端,后端重定向到目标平台并得到一个代码。根据登录提供者的设置,通常可以直接在此时向UI传递访问令牌,如果您试图进行无服务器操作。 - 您的后端使用该代码请求访问/刷新令牌。 - 获得访问/刷新令牌后,您保存它们安全地,然后有以下选项:
1. 直接向UI交付访问令牌。因此,UI可以直接向您授权的提供者发出请求。 2. 生成自己的令牌(例如JWT)和刷新令牌,并将其提供给UI。如果UI需要从提供程序获取数据,则使用您的令牌调用您的后端,您在内部管理对提供程序的调用。
选项2可能更容易处理多个提供程序,例如Facebook&Google&Dropbox,并且您有一个服务器来管理令牌。这是更经典的做法。
选项1是无服务器的,只需将其重定向回您的应用程序并要求UI执行必要的身份验证流程,在UI代码中管理令牌和其他内容。

非常详细,谢谢。我选择了哈希,但是由于我不想让用户在地址栏中看到令牌,所以我使用window.history.replaceState来去掉它。这是被认为是一种hack还是正常行为(或者哈希通常只是被忽略了)? - idlackage
@idlackage 首先要剥离URL中的内容,这是必须的。我认为replaceState的调用是可以接受的,只要你能够跨浏览器使用它。 - Catalyst
另外,@idlackage,如果您想为返回的用户保留状态,可以将令牌存储在localstorage或其他地方。请记得在存储中以及在URL中检查它,如果您选择这条路线:P我总是第一次搞砸状态逻辑。 - Catalyst
1
嗨@idlackage,我发现你的问题非常相关,我也陷入了类似的情况,请提供链接,如果你已经将代码推送到github上。 - mk1024

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接