Django, JWT, React перенаправляют на другую базу страниц в другой группе после входа в систему

У меня есть 2 роли: член и персонал, и я хочу перенаправить на разные страницы в зависимости от ролей пользователей, используя имя пользователя и пароль, например. после входа в систему в качестве участника будет перенаправлено на страницу участника, а в качестве сотрудника будет перенаправлено на страницу onlystaff. Как я могу это сделать. Я использую React Django JWT и Material UI.

код:

axios.js

const baseURL = 'http://127.0.0.1:8000/api/';

const axiosInstance = axios.create({
    baseURL: baseURL,
    timeout: 5000,
    headers: {
        Authorization: localStorage.getItem('access_token')
            ? 'JWT ' + localStorage.getItem('access_token')
            : null,
        'Content-Type': 'application/json',
        accept: 'application/json',
    }, 
});

axiosInstance.interceptors.response.use(
    (response) => {
        return response;
    },
    async function (error) {
        const originalRequest = error.config;

        if (typeof error.response === 'undefined') {
            alert(
                'A server/network error occurred. ' +
                    'Looks like CORS might be the problem. ' +
                    'Sorry about this - we will get it fixed shortly.'
            );
            return Promise.reject(error);
        }

        if (
            error.response.status === 401 &&
            originalRequest.url === baseURL + 'token/refresh/'
        ) {
            window.location.href = '/login/';
            return Promise.reject(error);
        }

        if (
            error.response.data.code === 'token_not_valid' &&
            error.response.status === 401 &&
            error.response.statusText === 'Unauthorized'
        ) {
            const refreshToken = localStorage.getItem('refresh_token');

            if (refreshToken) {
                const tokenParts = JSON.parse(atob(refreshToken.split('.')[1]));
                const now = Math.ceil(Date.now() / 1000);
                console.info(tokenParts.exp);

                if (tokenParts.exp > now) {
                    return axiosInstance
                        .post('/token/refresh/', { refresh: refreshToken })
                        .then((response) => {
                            localStorage.setItem('access_token', response.data.access);
                            localStorage.setItem('refresh_token', response.data.refresh);

                            axiosInstance.defaults.headers['Authorization'] =
                                'JWT ' + response.data.access;
                            originalRequest.headers['Authorization'] =
                                'JWT ' + response.data.access;

                            return axiosInstance(originalRequest);
                        })
                        .catch((err) => {
                            console.info(err);
                        });
                } else {
                    console.info('Refresh token is expired', tokenParts.exp, now);
                    window.location.href = '/login/';
                }
            } else {
                console.info('Refresh token not available.');
                window.location.href = '/login/';
            }
        }

        return Promise.reject(error);
    }
);

export default axiosInstance;

Логин.js

export default function LogIn() {
    let history = useHistory();
    const initialFormData = Object.freeze({
        username: '',
        password: '',
    });

const [formData, updateFormData] = useState(initialFormData);

const handleChangeEvent = (e) => {
    updateFormData({
        ...formData,
        [e.target.name]: e.target.value.trim(),
    });
};

const handleSubmit = (e) => {
    e.preventDefault();
    console.info(formData);

    axiosInstance
        .post(`token/`, {
            username: formData.username,
            password: formData.password,
        })
        .then((res) => {
            localStorage.setItem('access_token', res.data.access);
            localStorage.setItem('refresh_token', res.data.refresh);
            axiosInstance.defaults.headers['Authorization'] =
                'JWT ' + localStorage.getItem('access_token');
                history.push("/home");
            
        });
};
return (
    <Box component = "form" onSubmit = {handleSubmit} noValidate sx = {{ mt: 1, padding: 2 }}>
      <TextField
           margin = "normal"
           required
           id = "username"
           label = "username"
           name = "username"
           autoComplete = "username"
           autoFocus
           onChange = {handleChangeEvent}/>

      <TextField
        margin = "normal"
        required
        name = "password"
        label = "password"
        type = "password"
        id = "password"
        autoComplete = "current-password"
        onChange = {handleChangeEvent}/>
                        
         <Button type = "submit" onClick = {handleSubmit}>
                 LOG IN
          </Button>            
          </Box>    
);}

urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('core.urls')),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

в свой TokenObtainPairView.as_view() добавьте role пользователя или redirectPath в зависимости от роли в ответ. Затем внутри вашего handleSubmit добавьте это:


            localStorage.setItem('access_token', res.data.access);
            localStorage.setItem('refresh_token', res.data.refresh);
            axiosInstance.defaults.headers['Authorization'] =
                'JWT ' + localStorage.getItem('access_token');


            history.push(res.data.redirectPath); // add this

Редактировать

Вы можете отредактировать сам JWT в django и прочитать его с токена во внешнем интерфейсе, согласно этому

оно работает! Большое спасибо, что поделились.

sunn flower 17.03.2022 17:11

красивый! Я думал, что мой ответ был довольно расплывчатым. Поздравляю с решением — вы вернули роль как часть данных ответа или закодировали ее в JWT?

rymanso 17.03.2022 17:38

Я закодировал его, и он работает отлично.

sunn flower 17.03.2022 17:40

Другие вопросы по теме

Похожие вопросы

Реагировать на ввод, я определил состояние в начальное состояние, но все равно получаю предупреждение о смене неконтролируемого на контролируемый ввод
Redux useselector возвращает неопределенное значение, когда я пытался найти значение из массива состояний redux в соответствии с идентификатором useParams
Передача свойств интерфейса Typescript дочернему компоненту возвращает несуществующие свойства
Вопросительный знак в ответной нативной навигации при использовании экспо/векторных значков
Слияние службы направлений Google и результатов направлений
Получение элемента, который был нажат в функциональном компоненте в React
У меня проблемы с Redujx-toolkit
Проблема определения, является ли это участком земли в массиве карты земли
Отправка нескольких данных с помощью Axios
Как передать setState в другую функцию и использовать его для целевого значения из выбора материала-интерфейса и обработки изменения, ошибка «значение не определено»