下一个 js redux-observable 使用 cookie 的持久身份验证令牌
next js redux-observable persistent auth token using cookie
我一直在尝试实现react server-side-rendering using next, and redux-observable,现在我想实现auth
登录时
- 点击登录
- 派遣登录
- 设置登录类型
- 设置登录数据
- 调用后端 api auth/signin
- 如果响应显示令牌已过期
- 呼叫支持 api auth/refresh 使用 refreshToken
- 根据 auth/refresh 响应令牌设置 cookie
- 根据 auth/refresh 响应设置身份验证数据
- 其他
- 根据 auth/signin 响应令牌设置 cookie
- 根据 auth/signin 响应设置身份验证数据
关于访问需要授权的页面
- 检查名为
token
的 cookie
- 如果存在
- 回调apiauth/me授权
- 如果响应显示令牌已过期
- 呼叫支持 api auth/refresh 使用 refreshToken
- 根据 auth/refresh 响应令牌设置 cookie
- 根据auth/refresh
设置授权数据
- 其他
- 根据 auth/me 响应设置身份验证数据
- 其他
- 重定向到登录
上面的步骤发生在epics里面,如下
/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()
将始终 return ''
将始终调度 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的授权库,如下
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')
是的,我本可以在 epics 上使用 setToken()
,只是想直接测试 cookie 设置方法
更新:
- 尽管它不在控制台 > 应用程序 > Cookies 中,但它似乎存在于每个页面上,因为它正在打印正确的标记,如果我在组件渲染方法中
console.log(getToken())
- 但是每次我刷新页面,它都不见了。有点像它被存储在 redux 状态,这很奇怪
更新#2:
好的,我想我设法让它工作了,事实证明我们需要 2 种类型的 cookie,服务器端(刷新时生成的)和客户端(坚持导航),所以我的原因无法在 epics 上获取令牌,因为它不是从服务器端传递的(至少这是我的理解)
受此问题的启发 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% 明白这是如何解决我的问题的,但我现在就这样了
我一直在尝试实现react server-side-rendering using next, and redux-observable,现在我想实现auth
登录时
- 点击登录
- 派遣登录
- 设置登录类型
- 设置登录数据
- 调用后端 api auth/signin
- 如果响应显示令牌已过期
- 呼叫支持 api auth/refresh 使用 refreshToken
- 根据 auth/refresh 响应令牌设置 cookie
- 根据 auth/refresh 响应设置身份验证数据
- 其他
- 根据 auth/signin 响应令牌设置 cookie
- 根据 auth/signin 响应设置身份验证数据
- 如果响应显示令牌已过期
- 派遣登录
关于访问需要授权的页面
- 检查名为
token
的 cookie- 如果存在
- 回调apiauth/me授权
- 如果响应显示令牌已过期
- 呼叫支持 api auth/refresh 使用 refreshToken
- 根据 auth/refresh 响应令牌设置 cookie
- 根据auth/refresh 设置授权数据
- 其他
- 根据 auth/me 响应设置身份验证数据
- 其他
- 重定向到登录
- 如果存在
上面的步骤发生在epics里面,如下
/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()
将始终 return ''
将始终调度 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的授权库,如下
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')
是的,我本可以在 epics 上使用 setToken()
,只是想直接测试 cookie 设置方法
更新:
- 尽管它不在控制台 > 应用程序 > Cookies 中,但它似乎存在于每个页面上,因为它正在打印正确的标记,如果我在组件渲染方法中
console.log(getToken())
- 但是每次我刷新页面,它都不见了。有点像它被存储在 redux 状态,这很奇怪
更新#2:
好的,我想我设法让它工作了,事实证明我们需要 2 种类型的 cookie,服务器端(刷新时生成的)和客户端(坚持导航),所以我的原因无法在 epics 上获取令牌,因为它不是从服务器端传递的(至少这是我的理解)
受此问题的启发 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% 明白这是如何解决我的问题的,但我现在就这样了