[英]Logout user when jwt expires in react/redux
我正在使用 localstorage 在我的 react/redux 应用程序中存储 jwt 以进行身份验证。 如果他们的令牌过期,我试图让用户注销。 我让它工作的一种方法是在后端使用我的 authMiddleware.js 来发送error.message
并将有效负载设置为等于错误变量,然后在 useEffect 中,如果错误是jwt expired
我运行我的注销function(它只是清除本地存储)并将错误重置为 null。 如下所示:
authMiddleware.js:
const jwt = require("jsonwebtoken");
const User = require("../models/user");
const protect = async (req, res, next) => {
let token = req.body.token;
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.id).select("-password");
next();
} catch (error) {
res.status(400).json({ message: error.message });
}
};
module.exports = { protect };
投资组合切片:
export const getCurrentHoldings = createAsyncThunk(
"/portfolio/getCurrentHoldings",
async (value, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token;
const userID = thunkAPI.getState().auth.user._id;
const newObj = {
token: token,
userID: userID,
};
let url = `http://localhost:3001/api/portfolio/getCurrentHoldings`;
const response = await axios.post(url, newObj);
console.log("New request ran in getCurrentHoldings");
return response.data;
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
const initialState = {
error: null,
status: "idle",
holdings: null,
jwtError: null,
};
export const portfolioSlice = createSlice({
name: "portfolio",
initialState,
reducers: {
reset: (state) => initialState,
},
extraReducers(builder) {
builder
.addCase(getCurrentHoldings.pending, (state, action) => {
state.status = "loading";
})
.addCase(getCurrentHoldings.fulfilled, (state, action) => {
state.status = "success";
state.holdings = action.payload;
console.log(state.holdings);
})
.addCase(getCurrentHoldings.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
state.jwtError = action.payload;
})
},
});
投资组合.js:
useEffect(() => {
if (jwtError == "jwt expired") {
dispatch(logout());
dispatch(reset());
}
}, [jwtError]);
这个解决方案的问题是我有多个切片,我需要为每个切片添加一个类似的变量,并且 useEffect 会增长并开始看起来像:
useEffect(() => {
if (jwtError == "jwt expired") {
dispatch(logout());
dispatch(reset());
}
if (jwtError1 == "jwt expired") {
dispatch(logout());
dispatch(reset1());
}
if (jwtError2 == "jwt expired") {
dispatch(logout());
dispatch(reset2());
}
}, [jwtError, jwtError1, jwtError2]);
因此这个解决方案是不可扩展的,我认为解决这个问题的一种方法是让一些切片从另一个切片访问数据,这样至少 useEffect 会减少到原始大小并且是可扩展的,但我发现减速器只能访问他们拥有 state 因此更多地研究这个问题我发现了一些与此相关的帖子,我得到了以下建议
现在我对上述所有解决方案的一个问题是,是否应该在前端、后端或两者上解决这个问题? 由于中间件和 instance.interceptors 解决方案看起来像是在前端解决的。 我想知道这是否存在安全风险,以及您是否还应该使用后端中间件。
我还想知道使用 cookies 代替 useState 是否只是最佳实践,但无论哪种方式,我都想用 localstorage 来实现它。
最后,我想要一个最佳实践,了解如何使用 redux 进行反应,以及代码在我的设置中可能是什么样子。
更新:我目前正在尝试的解决方案是 redux 中间件,我无法在前端解码令牌,在反应项目中安装 jsonwebtoken 会导致错误: Module not found: Error: Can't resolve 'crypto' in myfile
. 据我所知,如果我要按照中间件链接中的建议对其进行解码,我将需要在前端使用这个库。
因此,更多地研究这个问题,我发现了一些与此相关的帖子,我得到了以下建议:1.使用 cookies 而不是 localstate 2.使用中间件和 3.使用 instance.interceptors
您得到的建议很棒,我肯定会使用仅 http cookie 来存储令牌(更安全,因为与 JS 运行时分开,没有恶意 js 代码可以看到它)和redux 中间件和axios 拦截器。
我目前正在尝试的解决方案是 redux 中间件,我无法在前端解码令牌,在 react 项目中安装 jsonwebtoken 会导致错误:找不到模块:错误:无法解析 myfile 中的“加密”。 据我所知,如果我要按照中间件链接中的建议对其进行解码,我将需要在前端使用这个库。
如果您使用的是https://www.npmjs.com/package/jsonwebtoken
,这似乎是仅 Node.js 的实现,不适用于浏览器。 查看JWT 验证客户端? 建议https://github.com/auth0/jwt-decode
在浏览器中对您来说应该足够了。
如果您不使用基于 http-only cookie 的解决方案 go,则有一个更优雅的解决方案:您可以解码 JWT,读取到期时间,然后安排setInterval
) 刷新令牌。 如果此操作失败,function 可以调度一个操作,将用户注销并将 redux state 重置为您需要的状态。 这是一种更主动的解决方案,因为您无需等到由于令牌过期而对后端的请求失败 - 毕竟您知道它何时会过期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.