与React挂钩的React-Router-Dom不会重定向以纠正路线



我是新来的反应,我敢肯定有一个我不明白的解释,但是我找不到答案...

如果用户登录,我想应用程序,所以我遵循了一些指南并创建了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

相关内容

  • 没有找到相关文章

最新更新