我一直在尝试使用next和redux-observable来实现反应服务器端渲染,现在我想实现 auth
登录时
- 点击登录
- 签到
- 设置登录类型
- 设置登录数据
- 调用后端 api 身份验证/登录
- 如果响应说令牌已过期
- 使用 refreshToken 调用支持的 api auth/refresh
- 根据身份验证/刷新响应令牌设置 cookie
- 根据身份验证/刷新响应设置身份验证数据
- 别的
- 根据身份验证/登录响应令牌设置 cookie
- 根据身份验证/登录响应设置身份验证数据
- 如果响应说令牌已过期
- 签到
关于访问需要身份验证的页面
- 检查调用的 cookie
token
- 如果存在
- 调用支持的 api auth/me 进行授权
- 如果响应说令牌已过期
- 使用 refreshToken 调用支持的 api auth/refresh
- 根据身份验证/刷新响应令牌设置 cookie
- 根据 auth/refresh 设置 auth 数据
- 别的
- 根据 auth/me 响应设置 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 被保存,并且它打印令牌就好了,说它在那里,但是当我在浏览器控制台 > 应用程序 > Cookies 下检查时,什么都没有
所以在下面的 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 设置方法
更新:
- 似乎尽管它不在控制台 > 应用程序 > Cookies 中,但它存在于每个页面上,因为如果我
console.log(getToken())
在组件渲染方法中这样做,它正在打印正确的令牌 - 但是每次我刷新页面时,它就消失了。有点像它被存储在一个 redux 状态,这很奇怪
更新#2:
好的,我想我设法让它工作,事实证明我们需要两种类型的 cookie,服务器端(刷新时生成的)和客户端(坚持导航),所以我无法做到的原因在史诗上获取令牌,因为它不是从服务器端传递的(至少这是我的理解)