如何在 ReactJS 上使用 JWT 令牌注销

时间:2021-07-23 14:49:46

标签: reactjs api react-router jwt

我在 nodeJS 中使用 API,在 ReactJS 中使用 APP。在 nodeJS 上,我正在进行 JWT 令牌验证。在 reactJS 中,我用来检查它是否有效,否则我要求再次进行身份验证。现在我将 JWT 令牌保存在 localStorage 中,如果您有更安全的东西,请告诉我。

我的问题:

  1. 向API发送请求等待响应太慢(2 秒)。
  2. token和page change的时间到了就去login,在login的时候锁在同一个页面(login),只有 重新加载页面才能工作。
  3. 当令牌无效并且我更改页面时,页面完全空白。

问题 1:我可以在 APP 中验证令牌,而不是一直向 API 请求它,这是最正确的解决方案吗? 问题 2 和 3:我认为是在页面渲染之后进行验证的逻辑问题。

我的应用代码:

App.tsx

import AdminPrivateRoute from './AdminPrivateRoute';
import { AuthContextProvider } from './contexts/AuthContext';

export default function App() {
    return (
        <BrowserRouter>
            <AuthContextProvider>
                <Switch>
                    <Route path="/" exact component={Home} />
                    <AdminPrivateRoute path="/admin" component={Admin} />
                    <Route path="*" component={() => <h1>Page not found 404</h1>} />
                </Switch>
            </AuthContextProvider>
        </BrowserRouter>
    );
}

AdminPrivateRoute.tsx

import { getToken, logout } from './Auth';
import Api from './Api';

const AdminPrivateRoute = ({component: Component, ...rest}) => {
    useEffect(() => {
        // Here I make a fetch call to validate the token in the API
        Api.checkToken(getToken() || '').then(res => {
            if (!res.auth) {
                logout();
            }
        });
    })

    return (
        <Route
            {...rest}
            render={props =>
                isAuthenticated() ? (
                    <Component {...props} />
                ) : (
                    <SignIn />
                )
            }
        />
    );
};

Auth.ts

export const TOKEN_KEY = 'XYZ';
export const getToken = () => localStorage.getItem(TOKEN_KEY);
export const isAuthenticated = () => getToken() !== null; // I thought about validating the token right here in the app
export const setToken = (token: string) => {
    localStorage.setItem(TOKEN_KEY, token);
};
export const logout = () => {
    localStorage.removeItem(TOKEN_KEY);
};

AuthContextProvider.tsx(我删除了所有声明类型)

import Api from './Api';
import { setToken } from './Auth';

export function AuthContextProvider(props) {
    const [user, setUser] = useState();

    async function signIn({email, password}) {
        // TODO: Validations here

        const res = await Api.adminSignIn({email, password});

        if (!res.auth) {
            throw new Error(res.message);
        }

        if (res.token) {
            setToken(res.token);
        }

        const {name} = res.user;

        setUser({
            name,
        });
    }

    return (
        <AuthContext.Provider value={{user, signIn}}>
            {props.children}
        </AuthContext.Provider>
    );
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

这里是您问题的解决方案

问题 1

Send a request to the API and wait for the response is too slow (2 seconds).

解决方案

通过名称 loading 在您的组件中创建一个状态,默认情况下 false 在 api 调用之前将其更改为 true。如果加载状态为真,则在登录/登录按钮上显示微调器。当您收到 API 的响应时,将加载为 false,如果令牌经过身份验证且有效,则将其保存在 cookie 中 [因为 cookie 比本地存储更安全]

问题 2

When the time of the token and page change expired, it goes to login and when logging in, it locks on the same page (login), only reloading the page to work.

解决方案

这是因为当您在 localStorage 中存储时,我认为在重新加载时您会丢失 JWT 令牌,因此我建议您使用 Reducer 及其持久形式。

问题 3

When the token is invalid and I change the page, the page is completely blank.

解决方案

当令牌无效时,将用户重定向到登录页面

注意:

在每个 api 调用中发送您的 JWT 令牌以验证您的 api