如何使用 redux-thunk 处理 Redux 应用程序中的失败身份验证状态?
How do I deal with failed auth statuses in a Redux app using redux-thunk?
当服务器从 React/Redux Express 应用程序中的身份验证中间件发回 401 身份验证失败状态时,我正在努力处理客户端中的响应。
简而言之,在加载仪表板时,我正在向受保护的路由发出请求:
router.route('/')
.get(authenticate, controller.get)
Authenticate 是检查 JWT 令牌的中间件:
exports.authenticate = function(req, res, next) {
const authorizationHeader = req.headers['authorization']
let token
if (authorizationHeader) {
token = authorizationHeader.split(' ')[1]
}
if (token) {
jwt.verify(token, config.secrets.jwt, (err, decoded) => {
if (err) {
logger.log(err)
res.status(401).json({ error: 'Failed to authenticate' })
} else {
User.findById(decoded._id)
.select('-password')
.exec()
.then(user => {
if (!user) {
res.status(404).json({ error: 'No such user.' })
} else {
req.currentUser = user
next()
}
})
}
})
} else {
res.status(403).json({ error: 'No token provided.' })
}
}
所以如果认证失败,返回的状态是401。我正在研究如何在中间件中优雅地处理401状态并且:
- 删除作为 jwt 令牌的 localStorage 令牌
- 运行一个删除授权的函数header
- 调度一个 Redux 操作将 auth 设置回初始状态,这是一个 isAuthenticated 布尔值到 false,并且用户回到空 object。然后在应用程序中通过将用户重定向回登录页面来处理此问题
如前所述,我正在使用 thunk 中间件来处理异步操作(只是不知道如何处理 401 响应)
const configureStore = () => {
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
applyMiddleware(thunk)
)
return store
}
谢谢:)
更新
我想我可以在操作中使用 catch,然后查询 res.status 代码,然后清除令牌并将用户注销,但这似乎是重复的,我需要为每个需要的操作执行此操作身份验证。
有没有更简洁的方法?我在下面用来说明的代码:
export const fetchTransactions = () => dispatch => axios.get('/api/transactions')
.then(transactions => {
dispatch({
type: FETCH_TRANSACTIONS,
payload: transactions
})
}).catch(err => {
if (err.status === 401) {
localStorage.removeItem('mm-jwtToken')
setAuthToken(false)
dispatch(setCurrentUser({}))
}
})
最后我在 action creator 中处理了错误,捕获了错误,然后调用了一个 handleErr 函数:
- 已删除本地存储令牌
- 使用 false 调用了删除授权的函数 header
返回了为了从 Redux 存储中删除用户而需要分派的操作。
函数 handleErr (err) {
如果(err.status === 401){
localStorage.removeItem('mm-jwtToken')
setAuthToken(假)
return setCurrentUser({})
}
}
export const fetchTransactions = () => dispatch => axios.get('/api/transactions')
.then(交易 => {
派遣({
类型:FETCH_TRANSACTIONS,
有效载荷:交易
}) }, 错误 => {
调度(handleErr(错误))
})
当服务器从 React/Redux Express 应用程序中的身份验证中间件发回 401 身份验证失败状态时,我正在努力处理客户端中的响应。
简而言之,在加载仪表板时,我正在向受保护的路由发出请求:
router.route('/')
.get(authenticate, controller.get)
Authenticate 是检查 JWT 令牌的中间件:
exports.authenticate = function(req, res, next) {
const authorizationHeader = req.headers['authorization']
let token
if (authorizationHeader) {
token = authorizationHeader.split(' ')[1]
}
if (token) {
jwt.verify(token, config.secrets.jwt, (err, decoded) => {
if (err) {
logger.log(err)
res.status(401).json({ error: 'Failed to authenticate' })
} else {
User.findById(decoded._id)
.select('-password')
.exec()
.then(user => {
if (!user) {
res.status(404).json({ error: 'No such user.' })
} else {
req.currentUser = user
next()
}
})
}
})
} else {
res.status(403).json({ error: 'No token provided.' })
}
}
所以如果认证失败,返回的状态是401。我正在研究如何在中间件中优雅地处理401状态并且:
- 删除作为 jwt 令牌的 localStorage 令牌
- 运行一个删除授权的函数header
- 调度一个 Redux 操作将 auth 设置回初始状态,这是一个 isAuthenticated 布尔值到 false,并且用户回到空 object。然后在应用程序中通过将用户重定向回登录页面来处理此问题
如前所述,我正在使用 thunk 中间件来处理异步操作(只是不知道如何处理 401 响应)
const configureStore = () => {
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
applyMiddleware(thunk)
)
return store
}
谢谢:)
更新 我想我可以在操作中使用 catch,然后查询 res.status 代码,然后清除令牌并将用户注销,但这似乎是重复的,我需要为每个需要的操作执行此操作身份验证。
有没有更简洁的方法?我在下面用来说明的代码:
export const fetchTransactions = () => dispatch => axios.get('/api/transactions')
.then(transactions => {
dispatch({
type: FETCH_TRANSACTIONS,
payload: transactions
})
}).catch(err => {
if (err.status === 401) {
localStorage.removeItem('mm-jwtToken')
setAuthToken(false)
dispatch(setCurrentUser({}))
}
})
最后我在 action creator 中处理了错误,捕获了错误,然后调用了一个 handleErr 函数:
- 已删除本地存储令牌
- 使用 false 调用了删除授权的函数 header
返回了为了从 Redux 存储中删除用户而需要分派的操作。
函数 handleErr (err) { 如果(err.status === 401){ localStorage.removeItem('mm-jwtToken') setAuthToken(假) return setCurrentUser({}) } }
export const fetchTransactions = () => dispatch => axios.get('/api/transactions') .then(交易 => { 派遣({ 类型:FETCH_TRANSACTIONS, 有效载荷:交易 }) }, 错误 => { 调度(handleErr(错误)) })