如何使用 express.js 将 cookie 值传递给所有路由?

How to pass cookie value to all routes with express.js?

我正在试验 Next.js,它使用 Express.js 作为服务器。我想通过检查用户的身份验证 cookie 是否存在(cookie 在登录时在客户端上设置)来验证服务器上的用户。

我是这样做的(我正在自定义 Next 默认 server.js 文件):

const express = require( 'express' )
const next = require( 'next' )

const cookiesMiddleware = require( 'universal-cookie-express' )
const dev = process.env.NODE_ENV !== 'production'
const app = next( { dev } )
const handle = app.getRequestHandler()

app.prepare().then( async () => {

    const server = express()

    server.use( cookiesMiddleware() )

    server.get( '/news', ( req, res ) => {
        const actualPage = '/news'
        const userID = req.universalCookies.get( 'userID' )
        const queryParams = { userID: userID }
        app.render( req, res, actualPage, queryParams )
    })  

    server.get( '*', ( req, res ) => {
        return handle( req, res )
    }) 

    server.listen( 3000, ( err ) => {
        if( err ) throw err
        console.log( '> Ready on http://localhost:3000' )
    })

})

所以基本上我使用 universal-cookie-express 包作为中间件从请求中读取 userID cookie,并将其作为参数传递给 /news 路由,这有自己的特殊 server.get,因为它必须根据 Next.js 说明使用自己的页面呈现。

然后在新闻页面中,我得到getInitialProps中的cookie值:

static async getInitialProps( { query } ) {
    const { userID } = query
    return { userID }
}

render() {
    return <p>The user ID is { this.props.userID }</p>
}

非常好。

顺便说一句,上面的代码有效。问题是我有几条不同的路线,不想在每个 server.get 函数中读取 cookie。所以我的问题是,如何读取 userID cookie 并将其传递给所有路由,以及如何在每个页面中访问它?

有几种方法可以实现:

  1. 使用 React 状态管理 (redux/fluxible).

    Read more about redux

    Read more about fluxible

  2. 使用 react-cookies 依赖项.

import { Component } from 'react'
import cookie from 'react-cookies'

class MyApp extends Component {
  constructor () {
    super()
    this.onLogin = this.onLogin.bind(this)
    this.onLogout = this.onLogout.bind(this)
  }

  componentWillMount() {
    // Get the userID value from react-cookie
    this.state =  { userId: cookie.load('userId') }
  }

  onLogin(userId) {
    this.setState({ userId })
    // Store the cookie in react-cookie
    cookie.save('userId', userId, { path: '/' })
  }

  onLogout() {
    // Destroy the cookie from react-cookie
    cookie.remove('userId', { path: '/' })
  }

  render() {
    const { userId } = this.state
    return (
      <div />
    );
  }
}

  1. 使用 window sessionStorage.

    Sessionstorage 为每个给定的来源维护一个单独的存储区域,该区域在页面会话期间可用(只要浏览器打开,包括页面重新加载和恢复)。一旦浏览器关闭并重新打开,会话自动销毁。

    // Store the cookie
    sessionStorage.setItem("userId", userId);
    // Get the value of cookie
    sessionStorage.getItem("userId");
    

我发现自己是一个非常巧妙的解决方案。我刚刚在设置路线之前添加了以下内容:

server.use( ( req, res, next ) => {
    req.userID = req.universalCookies.get( 'userID' )
    req.userToken = req.universalCookies.get( 'userToken' )
    next()
})   

这通过将 cookie 附加到 req 对象,使每个路由都可以使用 cookie。所以在服务器上,您可以按如下方式访问它:

server.get( '/news', ( req, res ) => {
    console.log( 'User ID is', req.userID )
})  

并且在客户端上,如果您像我一样使用 Next,则可以在 getInitialProps 中访问它:

static async getInitialProps( { req } ) {
    console.log( 'User ID is', req.userID ) 
}