使用cookie

时间:2018-03-20 10:56:00

标签: authentication cookies authorization redux-observable nextjs

我一直在尝试使用reactnext实现redux-observable服务器端呈现,现在我想实现auth

登录

  • 点击登录
    • 发送登录信息
      • 设置登录类型
      • 设置登录数据
    • 致电后端api auth / signin
      • 如果响应表明令牌已过期
        • 使用refreshToken
        • 调用支持的api auth / refresh
        • 根据身份验证/刷新响应令牌设置cookie
        • 根据身份验证/刷新响应设置身份验证数据
      • 否则
        • 根据auth / signin响应令牌设置cookie
        • 根据身份验证/登录响应设置身份验证数据

访问需要验证的网页

  • 检查名为token的Cookie
    • 如果存在
      • 致电支持api auth / me授权
      • 如果响应表明令牌已过期
        • 使用refreshToken
        • 调用支持的api auth / refresh
        • 根据身份验证/刷新响应令牌设置cookie
        • 根据auth / refresh
        • 设置auth数据
      • 否则
        • 根据身份验证/我的回复设置身份验证数据
    • 否则
      • 重定向到登录

以上步骤发生在史诗内部,如下所示

/epics/signin.js

export const signinEpic = (action$, store) => action$
  .ofType(SIGNIN)
  .mergeMap(() => {
    const params = { ... }
    return ajax(params)
      .concatMap((response) => {
        const { name, refreshToken } = response.body
        if (refreshToken && name === 'TokenExpiredError') {
          const refreshParams = { ... }
          return ajax(refreshParams)
            .concatMap((refreshResponse) => {
              setToken(refreshResponse.body.auth.token)
              const me = { ... }
              return [
                authSetMe(me),
                signinSuccess(),
              ]
            })
            .catch(error => of(signinFailure(error)))
        }
        const me = { ... }
        setToken(response.body.auth.token)
        return [
          authSetMe(me),
          signinSuccess(),
        ]
      })
      .catch(error => of(signinFailure(error)))
  })

我做了一些console.log(Cookies.get('token'))以确保cookie被保存,并且它打印令牌就好了,说它在那里,但当我在浏览器控制台下检查>申请>饼干,什么都没有

因此,在下面的auth epic中,getToken()将始终返回'',它始终会发送authMeFailure(error)

/epics/auth.js

// this epic will run on pages that requires auth by dispatching `authMe()`
export const authMeEpic = action$ => action$
  .ofType(AUTH_ME)
  .mergeMap(() => {
    const params = {
      ...,
      data: {
        ...
        Authorization: getToken() ? getToken() : '', // this will always return ''
      },
    }
    return ajax(params)
      .mergeMap((response) => {
        const { name, refreshToken } = response.body
        if (refreshToken && name === 'TokenExpiredError') {
          const refreshParams = { ... }
          return ajax(refreshParams)
            .mergeMap((refreshResponse) => {
              setToken(refreshResponse.body.auth.token)
              const me = { ... }
              return authMeSuccess(me)
            })
            .catch(error => of(authMeFailure(error)))
        }
        const me = { ... }
        setToken(response.body.auth.token)
        return authMeSuccess(me)
      })
      .catch(error => of(authMeFailure(error)))
  })

我使用js-cookie来获取和设置Cookie

编辑:我实际上准备了一个包含getToken,setToken和removeToken的auth lib,如下所示

import Cookies from 'js-cookie'

export const isAuthenticated = () => {
  const token = Cookies.get('token')
  return !!token
}

export const getToken = () => Cookies.get('token')

export const setToken = token => Cookies.set('token', token)

export const removeToken = () => Cookies.remove('token')

是的,我本来可以在史诗上使用setToken(),只是试图直接测试cookie集方法

更新:

  • 似乎尽管它不在控制台>申请> Cookie,它存在于每个页面上,因为如果我在组件渲染方法中console.log(getToken())打印正确的标记
  • 但每次刷新页面时,它都消失了。有点喜欢它存储在redux状态,这很奇怪

更新#2:

好吧我认为我设法让它工作,事实证明我们需要两种类型的cookie,服务器端(刷新时生成的一个)和客户端(持续导航),所以我不是'能够在史诗上获得令牌,因为它没有从服务器端传递(至少这是我的理解)

1 个答案:

答案 0 :(得分:0)

受github上的这个问题comment的启发

yarn add cookie-parser

./server.js上的

(您需要有一个自定义服务器才能执行此操作)

const cookieParser = require('cookie-parser')

...

server.use(cookieParser())

on ./pages/_document.js

export default class extends Document {
  static async getInitialProps(...args) {
    // ...args in your case would probably be req
    const token = args[0].req ? getServerToken(args[0].req) : getToken()

    return {
      ...
      token,
    }
  }

  render() {
    ...
  }
}

./lib/auth.js或您放置令牌方法的任何地方

export const getServerToken = (req) => {
  const { token = '' } = req.cookies

  return token
}

export const getToken = () => {
  return Cookies.get('token') ? Cookies.get('token') : ''
}

我不是百分之百了解这是如何解决我的问题,但我现在就这样离开