- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Redux 应用程序和一个充当 OAuth 服务器的远程 API。根据典型的例程,用户将其凭据交换为 token ,然后应用程序使用该 token 来获取数据并在服务器上执行一些操作。该 token 存储在存储中,也存储在 sessionStorage
中。
现在,有时访问 token 会过期,但由于已收到刷新 token ,最好先尝试刷新,并且只有在出现错误时才注销用户。
我完全理解签署部分,从技术上讲,这意味着简单地调度某个操作。但如何简化 token 刷新例程呢?
我尝试过 redux-saga,但它非常冗长。我确实必须为依赖于远程 API 的每个操作部分复制代码,以确保每个类似的请求都会首先检查访问 token 及其是否尚未过期,然后设法刷新它。
我尝试做的另一件事是一个中间件,它期望某种类型的操作,并将对远程 API 的请求封装到 Promise 中。这种方法可行,但我很好奇是否还有其他方法可以做到。
有人曾经实现过这种(非常通用的)类型的事情吗?有什么想法可以自动更新 token 并且不因代码量的增加而生气吗?也许是高阶组件?
最佳答案
对于需要重复发生的代码以及需要无缝和通用的代码,中间件通常是最佳选择。它可以很简单,只需在创建存储时添加两行代码以包含中间件并编写一个简单的函数来为您处理 token 逻辑即可。
假设您将这样创建商店:
import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from './reducers';
import { browserHistory } from 'react-router';
import { routerMiddleware } from 'react-router-redux';
import tokenMiddleware from './middleware/token';
const finalCreateStore = compose(
applyMiddleware(
routerMiddleware(browserHistory),
tokenMiddleware,
),
window.devToolsExtension ? window.devToolsExtension() : f => f,
)(createStore);
然后您可以从某个地方以初始状态调用此函数。
const store = finalCreateStore(rootReducer, initialState);
这将使您能够对通过商店的所有操作执行某些操作。由于使用 Promise 处理 API 调用的中间件很常见,因此有些人更喜欢为此目的重复使用它并将两者捆绑在一起。
典型的中间件看起来像这样:
export const tokenMiddleware = ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') { // pass along
return action(dispatch, getState);
}
// so let's say you have a token that's about to expire
// and you would like to refresh it, let's write so pseudo code
const currentState = getState();
const userObj = state.authentication.user;
if (userObj.token && userObj.token.aboutToExpire) {
const config = getSomeConfigs();
// some date calculation based on expiry time that we set in configs
const now = new Date();
const refreshThreshold = config.token.refreshThreshold;
if (aboutToExpireAndIsBelowThresholdToRefresh) {
// refreshTheToken can be an action creator
// from your auth module for example
// it should probably be a thunk so that you can handle
// an api call and a promise within once you get the new token
next(refreshTheToken(userObj, someOtherParams);
}
}
....
return next(action);
}
您的刷新 token thunk 可能与此类似:
function refreshToken(user, maybeSomeOtherParams) {
const config = getSomeConfigs;
return dispatch => {
makeAPostCallWithParamsThatReturnsPromise
.then(result => dispatch(saveNewToken({
result,
...
})))
.catch(error => dispatch({
type: uh_oh_token_refresh_failed_action_type,
error,
}));
};
您可能会选择的另一种选择是在更改路线时处理此问题。
假设您在某处有一个顶级路由,用于需要身份验证和系统中存在有效用户的路由。我们将它们称为经过身份验证的路由
。
您可以使用定义 onChange
处理函数的顶级路由来包装这些经过身份验证的路由。像这样的事情:
<Route onChange={authEntry}>
<Route ... /> // authenticated routes
<Route ... />
</Route>
在创建这些路由并设置商店时,创建商店后,您可以将其绑定(bind)到名为 checkAuth
的函数。
const authEntry = checkAuth.bind(null, store)
另一种方法是将路由定义包装在一个函数中并将存储传递给它,然后您就可以进行相同的访问,但我发现这并不像这样干净(个人偏好)。
现在这个 checkAuth
会做什么?
类似这样的事情:
export function checkAuth (store, previous, next, replace, callback) {
const currentUser = store.getState().auth.user
// can possibly dispatch actions from here too
// store.dispatch(..).then(() => callback())..
// so you could possibly refresh the token here using an API call
// if it is about to expire
// you can also check if the token did actually expire and/or
// there's no logged in user trying to access the route, so you can redirect
if (!currentUser || !isLoggedIn(currentUser)) {
replace('/yourLoginRouteHere')
}
callback() // pass it along
}
这两者都应该足够通用,以便它们在集中位置为您提供可重用的代码。希望您会发现这些有帮助。
关于reactjs - 在 Redux 应用程序中提供 OAuth 访问 token 的策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38087605/
我有一个包含数字和整数的文件,我只想读取整数, 如果它们令人讨厌,请忽略宏,但是我只需要有整数,但是我必须确保还要读取字符串,然后忽略它们 我必须在这里修改什么: #include #include
我有一个这样格式化的txt文件: MyDepartureTown MyDestinationTown 123.45 Vehicle 12 我正在尝试将数据导入到我的 C 程序中。这是我用来实现这一目标
我创建了一个简单的文件,使用 flex,它生成了一个文件 lex.yy.c,现在,我想把它放到 C++ 程序中。 %{ #include %} %% stop printf("Stop co
我的一个程序用 c++ 代码生成一个大文件。有没有办法从另一个C++类调用将生成的代码插入其中? 这是一个小例子,可以清楚地说明我想要实现的目标。 生成的文件示例: FirstClass first
我需要了解我的程序“检查输入十六进制消息的第三个位置” 程序将采用十六进制值输入消息。例如0x0123456789abcdef 程序将检查输入消息的第三个位置,即 0 现在程序将采用另一条十六进制值的
当我将输入从输入文件重定向到 yacc 程序时,在它完成解析文件后,我希望 yacc 解析器打印其所做操作的摘要。如果我通过键盘输入内容然后按 Ctrl+D,我希望它执行相同的操作。有办法做到这一点吗
我正在扫描该文件,但它有两种不同的结构。 文件: ParisRoubaix "Marco MARCATO" 33 UAD ITA 26 5:43:31 ParisRoubaix "Sam BEWLEY
我想将winsock2.lib 添加到我的程序中,但不希望将其包含到最终的可执行文件中。有什么方法可以让我动态加载与winsock2关联的dll吗?如果没有,是否有任何 dll(Windows 附带)
我尝试了一个基本程序来将数据从数据库表检索到java程序中。编译结束后,运行代码时出现异常。控制台中没有显示错误。显示异常消息 import java.sql.*; public class clas
我想用 C++ 创建一个跨平台安装程序。它可以是任何压缩类型,例如 zip 或 gzip,像普通安装程序一样嵌入程序本身。我不想在不同的平台、linux 和 windows 上创建很多更改。如何跨平台
每次尝试用鼠标输入两个顶点时,我都会崩溃。我最近改变了组织每个形状的方式,以确保新形状与旧形状重叠。 这个项目的想法是制作各种交互式 Canvas 。用户可以在直线、三角形和矩形之间进行选择,然后选择
我想在我的程序中显示以下文本。当我在 python 中粘贴以下文本时,它会将反斜杠解释为转义序列并弄乱我的 ascii 艺术..任何解决这个问题的想法极客。这是我的文本想出现在我的节目中 _ _
我正在尝试加载名为 Tut16_ReadText.txt 的文件,并使其运行程序以输出其重或轻。 我收到了粘贴在下面的错误。我无法抽出时间让这个程序运行。谁能解释一下我必须做什么才能使这个程序正常工作
我想使用命令行将列表作为参数传递,例如: $python example.py [1,2,3] [4,5,6] 我希望第一个列表 [1,2,3] 成为 first_list,[4,5,6] 成为 se
在分析 C# 应用程序时,我发现名为“ThePreStub”的系统 (?) 方法中有相当多的 CPU 使用率。这是什么? 最佳答案 参见:CLR Inside out - The Performanc
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我正在用 Python 开发一个游戏,想知道如何给它自己的图标。我使用的是 Windows 计算机,没有安装 Python 的额外东西。哦,我也在使用 3.3 版,这甚至可能吗? P.S 我在 Sta
我正在使用 tkinter 使用 Python 开发一个项目,该项目将允许对 IP 地址进行地理定位。我有原始转换,我可以获取 IP 地址并知道城市、州、国家、经度、纬度等。我想知道是否有任何方法可以
我编写了一个程序,您可以在其中选择任意数字并将其与任意数字的幂相关联。代码运行正常,直到它到达某个部分,然后我必须输入一个字符以使其移动到代码的下一部分。这就是我的意思: #include int
我正在编写“HACKING Art Of Exploitation”一书练习 Convert2.c 第 61 页。 这是我的代码。下面是我的问题。 #include void usage(char
我是一名优秀的程序员,十分优秀!