使用存储在Redux中的JWT令牌在React通用应用中管理会话。没有饼干

时间:2018-06-21 17:49:00

标签: reactjs session redux jwt

我正在开发带有SSR的React应用,我可以说这是一个通用应用。我正在尝试建立会话管理逻辑,为此,我想使用Redux中存储的JWT令牌。我知道我可以使用cookie代替Redux存储,但是由于它们在后端无法轻松实现,因此我更喜欢Redux方法。

这是我的方法:

  1. 由于这是一个通用应用程序,因此有两个Redux存储区具有相同的数据:一个由服务器创建,另一个由前端存储。
  2. 进行身份验证时,服务器将检查名称/密码在数据库中是否匹配,并将会话数据的某些信息加密为令牌:{ name: Joe, email: joe@doe.com, sessionType: 1 }。没有密码或敏感数据存储在那里。
  3. 对于每个发送的请求,客户端会将令牌添加为标头作为Bearer。还不知道该怎么做!
  4. 对于收到的每个请求,服务器将检查标头中的承载令牌。如果它存在并且有效(不需要检查数据库,只需尝试对其进行解码),会将其作为data添加到data.session: [THETOKEN]

    // server/app.js
    import routes from '../shared/routes/routes'; // Object with my routes
    
    app.get('*', function(req, res, next) {
        // Save in activeRoute the route that matches actual url
        const activeRoute =
            routes.find((route) => {
                return matchPath(req.url, route);
            }) || {};
    
        var data = {};
        const token = req.headers.authorization;
        // If route needs auth and there is a valid token in headers
        if(activeRoute.needsAuth === true || someMethodThatValidateToken(token)){
            data.token = req.headers.authorization
        }
        const store = storeFactory(true, data);
        const appString = renderToString(
            <Provider store={store}>
                <CookiesProvider cookies={req.universalCookies}>
                    <StaticRouter location={req.url} context={context}>
                        <Route
                            path="/"
                            render={(props) => {
                                return <App {...props} isAuthed={true} />;
                            }}
                        />
                    </StaticRouter>
                </CookiesProvider>
            </Provider>
        );
        // Render template with data
        res.render('index', {
            body: appString,
            data: serialize(data), // Data for page
        });
    }
    
  5. 如您所见,服务器将创建一个商店,并将渲染应用并将其传递给<Provider store={store}>组件。还将data的内容作为<script>添加到html中的window.data标记中。

    // index.ejs
    <body>
        <div id="app"><%- body %></div>
        <script>window.data = <%- data %></script>
        <script src="/assets/bundle.js"></script>
    </body>
    
  6. 客户端将读取window.data,从中创建一个商店,然后渲染将应用商店放置在<Provider store={store}>组件中的应用程序。

    // client.app.js
    const store = storeFactory(false, window.data);
    // Sending the Router with Route component; App component sent inside render method to insert data
    hydrate(
        <Provider store={store}>
            <CookiesProvider>
                <BrowserRouter>
                    <Route
                    path="/"
                    render={(props) => {
                    return <App {...props} isAuthed={true} />;
                    }}
                    />
                </BrowserRouter>
            </CookiesProvider>
        </Provider>,
    
        document.getElementById('app')
    );
    
  7. 对于每条路由,一些逻辑都会检查是否需要会话,是否存在令牌以及令牌是否有效,并根据它呈现页面或重定向到/ login(尚未实现)。

我的问题是:

  • 您如何看待这种方法?在通用应用程序中还有更好的方法吗?
  • 在步骤5.中,具有加密令牌的数据公开给window对象,因此是公开的:这是一个问题吗?
  • 如何为每个发送到服务器的请求将承载令牌添加到标头中?

0 个答案:

没有答案