[英]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.