我是新来的反应,我敢肯定有一个我不明白的解释,但是我找不到答案...
如果用户登录,我想应用程序,所以我遵循了一些指南并创建了HOC(私有路),但由于某些原因,我一直在应用程序的登录页面中,
即使LocalStorage包含有效的JWT,我正在要求使用特定的路径(/Wallet/Portfolio),它仍在将我重定向到登录页面,有人可以帮助我理解这个问题(我正在使用Typescript,但我敢肯定它与该问题无关)
我的主要组件(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
}
@tholle帮助我理解了这个问题,因为最初未对用户进行身份验证(直到服务器 -> async施加JWT),我们需要在React Dom Switch中添加以下内容:
<BrowserRouter>
<Switch>
<PrivateRoute exact path="/wallet/portfolio" component={AppPortfolio} isSignedIn={isLoggedIn}/>
/*all other private routes here*/
{ isLoggedIn ? <Redirect to="/wallet/portfolio"/> : "" }
<Route exact path="/wallet/login" component={AppLogin} />
<Route exact path="/wallet/register" component={AppRegister} />
<Redirect to={isLoggedIn ? "/wallet/portfolio" : "/wallet/login"}/>
</Switch>
</BrowserRouter>
当然不利的是,如果用户登录,他将无法转到任何公共页面(例如注册),但是我可以使用它...
谢谢@tholle