Безопасно ли использовать реактивное состояние js для хранения токена аутентифицированного пользователя?

Я внедряю простую систему аутентификации пользователей с использованием реагирования js и узла js api. Вот что я делаю внутри метода ComponentWillMount:

1. проверка, если токен выходит (в localStorage)
2.Если он не выходит, то значение состояния 'token' останется пустым.
3.Если он существует, то проверяется, является ли он действительным, используя запрос к бэкэнду
4. Если токен действителен, то укажите 'token' как localstorage.token
5. Если токен недействителен, тогда значение состояния "токен" останется пустым

В методе рендеринга я добавил условный рендеринг, основанный на значении состояния "токен", т. е. если состояние "токен" пустое, тогда будет отображаться обычная страница, иначе она будет перенаправлена ​​на страницу пользователя.

Проблема в том, что я могу изменить значение состояния "токен", используя любой инструмент разработчика. И это вызывает лазейку при входе в систему с использованием поддельного токена. Чтобы избежать необходимости проверять правильность состояния "токен" каждый раз, когда оно изменяется, с помощью одного из методов жизненного цикла, таких как componentDidUpdate shouldComponentUpdate. Но, как уже упоминалось в официальной документации реагировать

shouldComponentUpdate существует только как оптимизация производительности. Не полагайтесь на него, чтобы "предотвратить" рендеринг, так как это может привести к ошибкам.

Использование componentDidUpdate бесполезно, так как он будет вызываться после того, как компонент уже будет изменен из-за изменения состояния.

Использование componentWillUpdate упоминается как небезопасный в официальной документации

Я не уверен, как я могу решить эту лазейку. Вот код для компонента

import React,{Component} from 'react';
import {
    BrowserRouter as Router,
    Route,
    Link,
    Switch,
    Redirect
} from 'react-router-dom';

import Home from './Home';
import Nav from './Nav';
import Login from './Login';
import Signup from './Signup';

class Out extends Component{
    constructor(){
        super();        

        this.state = {
            token : '',
            isLoading:false            
        }
        this.isLoading = this.isLoading.bind(this);
    }

    logout(){
        alert('logged out');
    }

    componentWillMount(){
        let {match} = this.props;
        this.navNoSessionRouteData = [
            {to:`${match.url}login`,name:'Login',key:'r1'},
            {to:`${match.url}signup`,name:'signup',key:'r2'},
            {to:`${match.url}`,name:'Home',key:'r3'}
        ];

        this.navNoSessionButtonData = [];

        this.setState({
            isLoading:true
        });

        const tokenVar = localStorage.getItem('token');
        if(tokenVar == null){
            console.log('not logged in');
            this.setState({
                isLoading:false
            });
        }else{            
            fetch('http://localhost:3000/api/account/verify?token='+tokenVar)
            .then(res=>res.json())
            .then(json=>{
                if(json.success){
                    console.log('logged in');
                    this.setState({
                        token : tokenVar,
                        isLoading:false
                    });
                }else{
                    this.setState({                 
                        isLoading:false,
                    });
                }
            });
        }
    }

    isLoading(){
        let {isLoading,token} = this.state;
        if(isLoading === true){
            return (
                <p>Loading...</p>
            );
        }
        else{
            let {match} = this.props
            console.log(token);
            return(
                <div>
                    {
                        (token)?<p>Logged In</p>:(<p>NOT logged IN</p>)
                    }
                    <div className = "row">
                        <Nav navRouteData = {this.navNoSessionRouteData}  navButtonData = {this.navNoSessionButtonData}/>
                    </div>
                        <div className="row justify-content-center">
                            <Switch>
                                <Route exact = {true} path={`${match.path}`} component={Home} />
                                <Route path={`${match.path}login`} component={Login}/>
                                <Route path={`${match.path}signup`} component={Signup}/>
                            </Switch>
                        </div>
                </div>
            )
        }
    }


    render(){    
        return(
            <div>
                {this.isLoading()}
            </div>
        )
    }
}

export default Out;

изображение показывает вошедшего в систему пользователя с использованием реального токена изображение показывает, что пользователь вышел из системы с пустым токеном изображение показывает вошедшего в систему пользователя с поддельным токеном

0 ответов

Просто чтобы повторить здесь, я бы ответил на два вопроса:

1. (Я думаю, что ближе к вашему вопросу): Если я могу редактировать переменные состояния React, как что-либо, что я показываю, безопасно?

Дело в том, что они МОГУТ перейти к пользовательскому интерфейсу, который требует, чтобы они вошли в систему, но когда они на самом деле переходят к запросу данных (либо к вашему бэкэнду, либо напрямую к вашей базе данных, такой как Firebase), то для этого им понадобится действительный токен. Ваш бэкэнд должен проверить это и не вернет никаких ценных данных.

2. Если я могу читать переменные состояния React, насколько безопасен мой токен от кражи и использования кем-то еще для запроса и записи данных?

Для этого посмотрите этот ответ

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