下一个使用 cookie 的 js redux-observable 持久认证令牌
Posted
技术标签:
【中文标题】下一个使用 cookie 的 js redux-observable 持久认证令牌【英文标题】:next js redux-observable persistent auth token using cookie 【发布时间】:2018-08-29 03:47:09 【问题描述】:我一直在尝试使用next 和redux-observable 实现react 服务器端渲染,现在我想实现身份验证
登录时
点击登录 调度登录 设置登录类型 设置登录数据 调用后端api auth/signin 如果响应显示令牌已过期 使用 refreshToken 调用支持的 api 身份验证/刷新 根据身份验证/刷新响应令牌设置 cookie 根据身份验证/刷新响应设置身份验证数据 其他 根据身份验证/登录响应令牌设置 cookie 根据身份验证/登录响应设置身份验证数据关于访问需要身份验证的页面
检查名为token
的 cookie
如果存在
调用支持的 api auth/me 进行授权
如果响应显示令牌已过期
使用 refreshToken 调用支持的 api 身份验证/刷新
根据身份验证/刷新响应令牌设置 cookie
根据身份验证/刷新设置身份验证数据
其他
根据身份验证/我的响应设置身份验证数据
其他
重定向到登录
上面的步骤发生在史诗内部,如下
/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被保存,它打印令牌就好了,说它在那里,但是当我在浏览器控制台>应用程序>cookies下检查时,什么都没有
因此,在下面的 auth epic 中,getToken()
将始终返回 ''
,而 authMeFailure(error)
将始终派发 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 获取和设置cookies
编辑:我实际上准备了一个包含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设置方法
更新:
似乎尽管它不在控制台 > 应用程序 > Cookies 中,但它存在于每个页面上,因为如果我在组件渲染方法中执行console.log(getToken())
,它会打印正确的令牌
但每次我刷新页面时,它都消失了。有点像它被存储在一个 redux 状态,这很奇怪
更新 #2:
好吧,我想我设法让它工作了,事实证明我们需要 2 种类型的 cookie,服务器端(刷新时生成的)和客户端(坚持导航),所以我没有的原因无法在史诗上获取令牌,因为它不是从服务器端传递的(至少这是我的理解)
【问题讨论】:
您可以尝试从 Cookies.set 中删除 path: '/' 吗?只是为了确保路径没有问题。 哇!你是对的,它的路径,我现在很为自己感到羞耻,谢谢btw! 不,很抱歉它仍然无法正常工作,不知道它以前的工作情况如何 尝试删除所有 Cookies.set 中的 path 选项 另外能否提供 getToken() 的代码? 我确实删除了所有 path 选项,顺便说一句,问题已用 lib/auth.js 更新 【参考方案1】:受此问题的启发 comment github
yarn add cookie-parser
在./server.js
上(您需要有一个自定义服务器才能执行此操作)
const cookieParser = require('cookie-parser')
...
server.use(cookieParser())
在./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') : ''
我不是 100% 明白这是如何解决我的问题的,但我现在就这样吧
【讨论】:
以上是关于下一个使用 cookie 的 js redux-observable 持久认证令牌的主要内容,如果未能解决你的问题,请参考以下文章