我的反應身份驗證背景關系(authProvider)和正確呈現我的應用程式頁面有一個非常奇怪的問題。目前,我的根應用程式如下所示:
const App = () => {
const authCtx = useContext(AuthState);
return(
<AuthStateProvider>
<BrowserRouter>
<Switch>
{!authCtx.isLoggedIn && <Route path="/admin" component={SignInUp} />}
{authCtx.isLoggedIn && <Route path="/admin" component={Admin} />}
<Redirect from="/" to="/admin/myDashboard" />
</Switch>
</BrowserRouter>
</AuthStateProvider>
)};
然后在我用來管理身份驗證背景關系的單獨檔案中,我嘗試從本地存盤中提取 JWT 并對其進行驗證。如果成功,則使用狀態變數(包括您在上面看到的“isLoggedIn”變數)更新背景關系。
const AuthState = React.createContext({
userName: "",
isLoggedIn: false,
authToken: null,
});
const AuthStateProvider = (props) => {
let token = null;
if(localStorage.getItem("token")) return token = localStorage.getItem("token");
const [ user, setUser ] = useState({
userName: "Anonymous",
isLoggedIn: false,
authToken: token,
});
const autoLogin = useCallback( async () => {
try {
const response = await axios({
method:'post',
url: 'http://127.0.0.1:3001/authEn'
headers: {
"Content-Type": "application/json",
"Authentication": user.authToken
}
});
if(response.status === 200){
//code to update context using setUser state handler
} else {
throw new Error("request failed");
}
} catch (e) {
console.log(e.message);
}
});
useEffect( async () => {
await autoLogin();
}, [autoLogin]);
return (
<AuthState.Provider
value={{
userName: user.userName,
isLoggedIn: user.isLoggedIn,
authToken: user.authToken
}}
>
{props.children}
</AuthState.Provider>
);
}
(我已經排除了我的 setUser 處理程式的代碼以盡量保持簡短。)所以問題是,截至目前,我只是想看看應用程式可以
A:在初始頁面加載/重新加載時檢查存盤的令牌
B:相應地將您導航到登錄或管理頁面。
如果本地存盤中有錯誤/沒有 JWT,該應用程式可以毫無問題地將您帶到登錄頁面。但是當我嘗試測驗當本地存盤中有有效令牌時應用程式是否可以正確導航到管理頁面(我有一個單獨的幫助函式來保存有效令牌),頁面加載,但沒有實際的管理儀表板. 相反,頁面上的所有內容都是顯示在視窗頂部的令牌本身,就好像它只是一個 html 頁面,其中一個 div 包含作為字串的令牌。我不知道為什么會這樣。當我嘗試呈現管理組件(洗掉“isLoggedIn”邏輯和 authStateProvider)時,一切正常。但是每次我嘗試以這種方式添加身份驗證時,事情開始變得奇怪。我是否遺漏了一些明顯的東西(通常是這種情況)?這只是一種非常愚蠢的方法嗎(通常也是這種情況)?或者這是一個低級的反應問題(我不是非常熟悉反應如何在引擎蓋下作業的所有復雜性。)
uj5u.com熱心網友回復:
我認為在 Switch 中設定條件是一種不好的做法。相反,您可以創建一個單獨的組件,如 ProtectedRoute 或使用高階組件 (HOC) 包裝您的頁面
- ProtectedRoute的第一種方式
如果您的包裹路線需要身份驗證,請在道具中傳遞 isProtected
// ProtectedRoute.js
import React, { useContext } from 'react';
import { Redirect } from 'react-router-dom';
const ProtectedRoute = ({
isProtected,
children,
}) => {
const { isLoggedIn } = useContext(AuthState);
if (isProtected && !isLoggedIn) {
return <Redirect to='/login' />;
}
return children
};
export default ProtectedRoute;
然后在您的交換機中:
<Switch>
{ /* Other routes */ }
<ProtectedRoute isProtected>
<Route path="/admin" component={Admin} />
</ProtectedRoute>
</Switch>
- 高鐵
// withAuth
import React, { useContext } from 'react';
import { Redirect } from 'react-router-dom';
const withAuth = (WrappedComponent: any) =>
function (props: any) {
const { isLoggedIn ) = useContext(AuthState);
if (!isLoggedIn) {
<Redirect to='/login' />
}
return <WrappedComponent {...props} />;
}
export default withAuth;
現在您可以無條件地在交換機中插入您的路由。如果您的組件需要身份驗證,請使用 withAuth 包裝它。
例子:
const NeedAuth = () => (
<div>Hello I need auth</div>
);
export default withAuth(NeedAuth)
uj5u.com熱心網友回復:
我想通了這個問題,是的,這是一個非常小的問題。在我檢查本地存盤上是否存盤了令牌的代碼行中,我使用了帶有 return 陳述句的 if 塊。不久前我看到這樣做允許將“if”陳述句完全寫在一行上,而不用括號 {} 封裝代碼。當時它真的只是一種風格選擇,但現在我看到當 if 陳述句運行時(即本地存盤中有一個令牌),其中的 return 陳述句覆寫了整個功能組件的 return 陳述句。因此,與其擁有一個背景關系檔案,它回傳一個包含您想要的孩子的提供程式(我的管理頁面路由器),它只是列印 authtoken。所以我回到了 If 陳述句的傳統樣式并洗掉了 return 陳述句,它作業正常!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/394333.html
標籤:javascript 反应 验证 公理 jwt
上一篇:引數1:無法從“Microsoft.EntityFrameworkCore.DbContextOptions”轉換為“string”
