Javascript 在将历史推送到路由器之前验证令牌

Javascript 在将历史推送到路由器之前验证令牌,javascript,reactjs,callback,Javascript,Reactjs,Callback,我相信这是一个非常简单的问题,但我不习惯异步/回调世界。 我制作了privaterout,以保护我的资源不被未经身份验证的用户攻击。如果我只检查存储器中的标记。它通常会推送到资源。但它不包括过时的令牌。然后我让它在继续之前用后端进行验证 问题: axios调用返回正确的值,但页面不会将经过身份验证的用户推送到正确的资源页面 console.log向我显示1然后并停留在登录页面 App.js const PrivateRoute = ({component: Component, isAuthor

我相信这是一个非常简单的问题,但我不习惯异步/回调世界。

我制作了
privaterout
,以保护我的资源不被未经身份验证的用户攻击。如果我只检查存储器中的
标记
。它通常会推送到资源。但它不包括过时的
令牌
。然后我让它在继续之前用后端进行验证

问题:
axios
调用返回正确的值,但页面不会将经过身份验证的用户推送到正确的资源页面
console.log
向我显示1
然后
并停留在登录页面

App.js

const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
  <Route
    {...otherProps}
    render={props => (
      isAuthorized() ? (<Component {...props} />) :
        (
          <Redirect to={
            {
              pathname: '/',
              state: {from: props.location},
            }
          }
          />
        )
    )}
  />
);

function verifyToken(isAuthenticated){
  if (isAuthenticated) {
    axios.post(`${BACKEND_URL}/api-token-verify/`, {
      token: getAuthToken()
    }).then((res) => {
        console.log('then');
        return true;
      })
      .catch((err) => {
        console.log('err');
        return false;
      });
  } else {
    console.log('ahaha');
    return false;
  }
}

// Deal with an ordinary outdated token. Hacked one will be handle on individual component
function hasToken() {
  const token = localStorage.getItem('authToken');
  const isAuthenticated = !((token === undefined) | (token === null));

  return verifyToken(isAuthenticated);
}


class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <BrowserRouter>
          <Switch>
            <Route exact path='/' component={Login}/>
            <PrivateRoute exact path='/simulator/' isAuthorized={hasToken} component={Simulator}/>
          </Switch>
        </BrowserRouter>
      </Provider>
    )
  }
}

export default App;
import React, {Component, Fragment} from 'react';
import {BrowserRouter, Redirect, Route, Switch} from 'react-router-dom';
import Simulator from "../../simulators/components/Simulators";
import Login from "../../frontpage/components/login";
import {connect} from 'react-redux';
import {CHECK_TOKEN} from "../../constants";

const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
  <Route
    {...otherProps}
    render={props => (
      isAuthorized() ? (<Component {...props} />) :
        (
          <Redirect to={
            {
              pathname: '/',
              state: {from: props.location},
            }
          }
          />
        )
    )}
  />
);


// Deal with an ordinary outdated token. Hacked one will be handle on individual component
function hasToken() {
  const token = localStorage.getItem('authToken');
  return !((token === undefined) | (token === null));
}


class Container extends Component {
  /*
  * In order to do redux staff and not to mess up with top most <App/>
  * Container has been created to contain them all
  *
  * */
  constructor(props) {
    super(props);
    this.props.validateToken();
  }

  render() {
    console.log(this.props);
    const {isAuthenticated, wrapper} = this.props;
    console.log(typeof this.props.wrapper);
    if((typeof this.props.wrapper) === 'function') {
      console.log('this is function');
      return (
        <Fragment>
          <BrowserRouter>
            <Switch>
              <Route exact path='/' component={Login}/>
              <PrivateRoute exact path='/simulator/' isAuthorized={this.props.wrapper} component={Simulator}/>
            </Switch>
          </BrowserRouter>
        </Fragment>
      )
    }else{
      console.log('wrapper is not a function');
      console.log(typeof this.props.wrapper);
      return null;
    }
  }
}

const mapStateToProps = ({verifyTokenReducer}, ownProps) => {
  return verifyTokenReducer
};

const validateToken = () => {
  return {
    type: CHECK_TOKEN,
    payload: undefined
  }
};

export default connect(mapStateToProps, {validateToken})(Container);
import {GOOD_TOKEN, INVALID_TOKEN} from "../constants";

function immediateReturnTrue(){
  return true;
}
function immediateReturnFalse(){
  return false;
}

export const VerifyTokenReducer = (state = {}, action) => {
  switch (action.type) {
    case GOOD_TOKEN:
      return {
        isAuthenticated: true,
        wrapper: immediateReturnTrue
      };
    case INVALID_TOKEN:
      return {
        isAuthenticated: false,
        wrapper: immediateReturnFalse
      };
    default:
      return state;
  }
};
Container.js

const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
  <Route
    {...otherProps}
    render={props => (
      isAuthorized() ? (<Component {...props} />) :
        (
          <Redirect to={
            {
              pathname: '/',
              state: {from: props.location},
            }
          }
          />
        )
    )}
  />
);

function verifyToken(isAuthenticated){
  if (isAuthenticated) {
    axios.post(`${BACKEND_URL}/api-token-verify/`, {
      token: getAuthToken()
    }).then((res) => {
        console.log('then');
        return true;
      })
      .catch((err) => {
        console.log('err');
        return false;
      });
  } else {
    console.log('ahaha');
    return false;
  }
}

// Deal with an ordinary outdated token. Hacked one will be handle on individual component
function hasToken() {
  const token = localStorage.getItem('authToken');
  const isAuthenticated = !((token === undefined) | (token === null));

  return verifyToken(isAuthenticated);
}


class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <BrowserRouter>
          <Switch>
            <Route exact path='/' component={Login}/>
            <PrivateRoute exact path='/simulator/' isAuthorized={hasToken} component={Simulator}/>
          </Switch>
        </BrowserRouter>
      </Provider>
    )
  }
}

export default App;
import React, {Component, Fragment} from 'react';
import {BrowserRouter, Redirect, Route, Switch} from 'react-router-dom';
import Simulator from "../../simulators/components/Simulators";
import Login from "../../frontpage/components/login";
import {connect} from 'react-redux';
import {CHECK_TOKEN} from "../../constants";

const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
  <Route
    {...otherProps}
    render={props => (
      isAuthorized() ? (<Component {...props} />) :
        (
          <Redirect to={
            {
              pathname: '/',
              state: {from: props.location},
            }
          }
          />
        )
    )}
  />
);


// Deal with an ordinary outdated token. Hacked one will be handle on individual component
function hasToken() {
  const token = localStorage.getItem('authToken');
  return !((token === undefined) | (token === null));
}


class Container extends Component {
  /*
  * In order to do redux staff and not to mess up with top most <App/>
  * Container has been created to contain them all
  *
  * */
  constructor(props) {
    super(props);
    this.props.validateToken();
  }

  render() {
    console.log(this.props);
    const {isAuthenticated, wrapper} = this.props;
    console.log(typeof this.props.wrapper);
    if((typeof this.props.wrapper) === 'function') {
      console.log('this is function');
      return (
        <Fragment>
          <BrowserRouter>
            <Switch>
              <Route exact path='/' component={Login}/>
              <PrivateRoute exact path='/simulator/' isAuthorized={this.props.wrapper} component={Simulator}/>
            </Switch>
          </BrowserRouter>
        </Fragment>
      )
    }else{
      console.log('wrapper is not a function');
      console.log(typeof this.props.wrapper);
      return null;
    }
  }
}

const mapStateToProps = ({verifyTokenReducer}, ownProps) => {
  return verifyTokenReducer
};

const validateToken = () => {
  return {
    type: CHECK_TOKEN,
    payload: undefined
  }
};

export default connect(mapStateToProps, {validateToken})(Container);
import {GOOD_TOKEN, INVALID_TOKEN} from "../constants";

function immediateReturnTrue(){
  return true;
}
function immediateReturnFalse(){
  return false;
}

export const VerifyTokenReducer = (state = {}, action) => {
  switch (action.type) {
    case GOOD_TOKEN:
      return {
        isAuthenticated: true,
        wrapper: immediateReturnTrue
      };
    case INVALID_TOKEN:
      return {
        isAuthenticated: false,
        wrapper: immediateReturnFalse
      };
    default:
      return state;
  }
};

这里的关键洞察是,
verifyToken
永远不会返回
true
,因为if分支不返回任何内容,而else分支返回
false
。您的承诺中的
返回true
的回调中。然后
,这意味着
返回true
不适用于函数
验证令牌
,而是
中的匿名函数。然后

为了解决这个问题,您需要从
verifyToken
函数返回承诺,并在
privaterout
组件中将其作为承诺处理。现在,渲染道具将承诺视为立即可用的值,而不是承诺。(您没有在任何地方使用
。然后

render={props=>(
isAuthorized()?():
(
)
)}

感谢您的快速回复。我现在试图通过添加中间函数来处理
Promise
,从而使
privaterout
保持原样。请让我知道我是否走错了路。@Sarit您应该让一些组件处理承诺,并使用
setState
将您的响应状态置于您是否已通过身份验证的状态。然后在三元代码中使用该状态,而不是
isAuthenticated
。非常感谢。问题解决了。我必须再添加一个
组件
,就像您所说的那样。解决方案是很长的张贴在这里IMO。那么你宝贵的意见应该是好的新来者。