簡體   English   中英

當使用 JWT 單擊某個鏈接時,如何重定向用戶登錄

[英]How can I redirect a user to login when a certain link is clicked using JWT

我試圖做到這一點,以便當用戶單擊某個鏈接(上傳組件)時,它會將他們重定向到登錄組件,並且我不確定如何在 React 中完成此任務。 我被引導到另一個已回答的問題,但這對我沒有幫助,因為我仍然對自己的設置需要做什么感到困惑。 我知道我需要創建自己的受保護路由(也許),但我看到其他人正在訪問 useContext 而我沒有任何包含上下文的文件。 我在 react dom 中使用版本 6。 我也在我的項目中使用 React 路由器和 redux,所以我知道我需要以某種方式訪問 state,只是不確定如何圍繞它思考,所以如果有人能提供幫助,我將不勝感激。 用戶通過 JWT 身份驗證存儲在本地存儲中。

應用程序.js:

import React, {useState, useEffect, useCallback} from 'react';
import {useDispatch, useSelector} from 'react-redux';
import {BrowserRouter as Router, Routes, Route} from 'react-router-dom'; //Switch was replaced by Routes in react-router-dom v6
import './App.css';
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import Home from './components/pages/Home';
import Uploads from './components/pages/Uploads';
import Account from './components/pages/Account';
import Login from './components/pages/Login';
import LogOut from './components/Logout';
import Register from './components/pages/Register';
import Profile from './components/pages/Profile';
import EditProfile from './components/pages/EditProfile';
import BoardAdmin from './components/pages/BoardAdmin';
import BoardModerator from './components/pages/BoardModerator';
import BoardUser from './components/pages/BoardUser';
import {logout} from './slices/auth';
import EventBus from './common/EventBus';

const App = () => {
    const [showModeratorBoard, setShowModeratorBoard] = useState(false);
    const [showAdminBoard, setShowAdminBoard] = useState(false);
    const {user: currentUser} = useSelector((state) => state.auth);
    const dispatch = useDispatch();

    useEffect(() => {
        if (currentUser) {
            setShowModeratorBoard(currentUser.roles.includes('ROLE_MODERATOR'));
            setShowAdminBoard(currentUser.roles.includes('ROLE_ADMIN'));
        } else {
            setShowModeratorBoard(false);
            setShowAdminBoard(false);
        }
    }, [currentUser]);

    return (
        <>
            <Router>
                <Navbar />
                <Routes>
                    <Route path='/' element={<Home />} />
                    <Route path='/create/upload' element={<Uploads />} />
                    <Route path='/my-account' element={<Account />} />
                    <Route path='/login' element={<Login />} />
                    <Route path='/logout' element={<LogOut />} />
                    <Route path='/register' element={<Register />} />
                    <Route path='/profile' element={<Profile />} />
                    <Route path='/profile/edit' element={<EditProfile />} />
                    <Route path='/user' element={<BoardUser />} />
                    <Route path='/mod' element={<BoardModerator />} />
                    <Route path='/admin' element={<BoardAdmin />} />
                </Routes>
                <Footer />
            </Router>
        </>
    );
};

export default App;

授權.js:

import {createSlice, createAsyncThunk} from '@reduxjs/toolkit';
import {setMessage} from './messages';
import AuthService from '../services/auth.service';
const user = JSON.parse(localStorage.getItem('user'));
export const register = createAsyncThunk(
    'auth/register',
    async ({username, email, password}, thunkAPI) => {
        try {
            const response = await AuthService.register(username, email, password);
            thunkAPI.dispatch(setMessage(response.data.message));
            return response.data;
        } catch (error) {
            const message =
                (error.response &&
                    error.response.data &&
                    error.response.data.message) ||
                error.message ||
                error.toString();
            thunkAPI.dispatch(setMessage(message));
            return thunkAPI.rejectWithValue();
        }
    }
);
export const login = createAsyncThunk(
    'auth/login',
    async ({username, password}, thunkAPI) => {
        try {
            const data = await AuthService.login(username, password);
            return {user: data};
        } catch (error) {
            const message =
                (error.response &&
                    error.response.data &&
                    error.response.data.message) ||
                error.message ||
                error.toString();
            thunkAPI.dispatch(setMessage(message));
            return thunkAPI.rejectWithValue();
        }
    }
);
export const logout = createAsyncThunk('auth/logout', async () => {
    await AuthService.logout();
});
const initialState = user
    ? {isLoggedIn: true, user}
    : {isLoggedIn: false, user: null};
const authSlice = createSlice({
    name: 'auth',
    initialState,
    extraReducers: {
        [register.fulfilled]: (state, action) => {
            state.isLoggedIn = false;
        },
        [register.rejected]: (state, action) => {
            state.isLoggedIn = false;
        },
        [login.fulfilled]: (state, action) => {
            state.isLoggedIn = true;
            state.user = action.payload.user;
        },
        [login.rejected]: (state, action) => {
            state.isLoggedIn = false;
            state.user = null;
        },
        [logout.fulfilled]: (state, action) => {
            state.isLoggedIn = false;
            state.user = null;
        },
    },
});
const {reducer} = authSlice;
export default reducer;

看起來在我的上傳文件中添加 if 語句使得登錄用戶可以訪問文件中的 h1 元素,但未經身份驗證的用戶不能。 所以它在一定程度上起作用,只是不重定向回登錄。

上傳.jsx:

import React from 'react';
import {Link} from 'react-router-dom';
import {useSelector} from 'react-redux';
function Uploads() {
    const {user: currentUser} = useSelector((state) => state.auth);
    if (!currentUser) {
        return <Link to='/login' />;
    }
    return (
        <>
            <h1 className='page'>UPLOADS</h1>
        </>
    );
}

export default Uploads;

呈現Link不強制導航,使用Navigation組件。

例子:

import React, { useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import { useSelector } from 'react-redux';

function Uploads() {
  const { user: currentUser } = useSelector((state) => state.auth);

  if (!currentUser) {
    return <Navigate to='/login' replace />;
  }
  return (
    <>
      <h1 className='page'>UPLOADS</h1>
    </>
  );
}

export default Uploads;

通常你會保護路由。 如果你想這樣做:

import { Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';

const PrivateRoutes = () => {
  const { user: currentUser } = useSelector((state) => state.auth);
  return currentUser 
    ? <Outlet />
    : <Navigate to="/login" replace />;
}

...

<Routes>
  <Route path='/' element={<Home />} />
  <Route element={<PrivateRoutes />}>
    <Route path='/create/upload' element={<Uploads />} />
    ... any other protected routes ...
  </Route>
  ... other unprotected routes ...
</Routes>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM