我是新来的反应者,我确定有一个我不理解的解释,但是我找不到答案...
如果用户已登录,我想使用该应用程序,因此我遵循了一些指南并创建了HOC(PrivateRoute),但由于某些原因,我一直停留在该应用程序的登录页面中,
即使localStorage包含有效的JWT,并且我要求输入特定的路径(/ wallet / portfolio),它仍会将我重定向到登录页面, 有人可以帮我理解这个问题吗(我正在使用打字稿,但我确定它与问题无关)
我的主要组件(App.tsx)
//imports...
export const App = () => {
const[jWTContext, setJWTContext] = useState(jWTContextInitialState);
const[isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
if (!isLoggedIn) {
jWTContext.isValid().then(loggedIn => {
setIsLoggedIn(loggedIn);
}
).catch(() => {setIsLoggedIn(false)});
}
});
return (
<JWTContext.Provider value={jWTContext}>
<BrowserRouter>
<Switch>
<PrivateRoute exact path="/wallet/portfolio" component={AppPortfolio} isSignedIn={isLoggedIn}/>
<Route exact path="/wallet/login" component={AppLogin} />
<Route exact path="/wallet/register" component={AppRegister} />
<Redirect to={isLoggedIn ? "/wallet/portfolio" : "/wallet/login"}/>
</Switch>
</BrowserRouter>
</JWTContext.Provider>
);
};
PrivateRoute.tsx(从网络指南中复制...)
import * as React from 'react';
import {Route, Redirect, RouteProps} from 'react-router-dom';
interface PrivateRouteProps extends RouteProps {
component: any;
isSignedIn: boolean;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, isSignedIn, ...rest } = props;
return (
<Route
{...rest}
render={(routeProps) =>
isSignedIn ? (
<Component {...routeProps} />
) : (
<Redirect
to={{
pathname: '/wallet/login',
state: { from: routeProps.location }
}}
/>
)
}
/>
);
};
export default PrivateRoute;
JWTContext.tsx(我的上下文提供程序):
import React from 'react';
import {JWTBody, JWTHeader, JWTToken} from "../interfaces/JWTToken"
export interface JWTContext {
jWTToken: JWTToken | null;
setJWTToken(jWTToken: JWTToken | null): void;
isValid(): Promise<boolean>;
updateFromLocalStorage(): (JWTToken | null);
}
export const jWTContextInitialState : JWTContext = {
jWTToken: initFromLocalStorage(),
setJWTToken: (jWTToken) => {
jWTContextInitialState.jWTToken = jWTToken;
},
isValid: async() => {
if (jWTContextInitialState.jWTToken) {
let response = await fetch("/auth/tokenvalid",{
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": JSON.stringify(jWTContextInitialState.jWTToken)}});
let res = await response.json();
if (res.code === 200)
return true;
}
return false;
},
updateFromLocalStorage: () => {
return initFromLocalStorage()
}
};
function initFromLocalStorage() {
let localStorageToken = localStorage.getItem("velonaJWT");
if (localStorageToken) {
return parseJwt(localStorageToken);
}
return null;
}
function parseJwt (token: string): JWTToken {
token = token.replace("Bearer ", "");
let tokenArray = token.split('.');
let header = tokenArray[0];
header = header.replace('-', '+').replace('_', '/');
let bufferHeader = Buffer.from(header, "base64");
let dataHeader: JWTHeader = JSON.parse(bufferHeader.toString());
let body = tokenArray[1];
body = body.replace('-', '+').replace('_', '/');
let bufferBody = Buffer.from(body, "base64");
let dataBody: JWTBody = JSON.parse(bufferBody.toString());
return ({
header: dataHeader,
body: dataBody,
sig: tokenArray[2]
});
//return JWTToken(JSON.parse(bufferHeader.toString()), JSON.parse(bufferBody.toString()), tokenArray[2])
}
export const JWTContext = React.createContext(jWTContextInitialState);
最后是(JWTToken.tsx->仅用于接口)
// represent velona WJT token
export interface JWTToken {
header: JWTHeader,
body: JWTBody,
sig: string,
}
export interface JWTHeader {
typ: string,
alg: string
}
export interface JWTBody {
sub: number,
jti: string,
authorities: Authorities[],
iat: number,
nbf: number,
exp: number,
environment: string
}
export enum Authorities {
ROLE_USER,
ROLE_TRUSTEE,
ROLE_EMPLOYEE,
ROLE_ADMIN
}
答案 0 :(得分:0)
@Tholle帮助我了解了这个问题, 因为起初用户未通过身份验证(直到JWT被服务器验证->异步),所以我们需要在react dom Switch中添加以下内容:
latitude
当然,缺点是,如果用户登录,他将无法进入任何公共页面(例如注册),但我可以接受...
感谢@Tholle