React 路由器身份验证流不会重定向到无效/过期的令牌



我的问题

我正在遵循来自 react-router 存储库的身份验证流示例进行客户端身份验证。

除了过期或无效令牌的情况外,一切都很好。 如果本地存储中没有令牌,则用户将被重定向到登录页面。 但是,如果本地存储中有令牌(即使令牌未在服务器上验证),重定向也不起作用。

感谢您的帮助

《守则》

索引.jsx

import React from 'react'
import ReactDom from 'react-dom'
import { Router, Route, IndexRoute, hashHistory } from 'react-router'
import App from './components/App'
import Request from './components/Request'
import Login from './components/Login'
import Dashbord from './components/Dashboard'
import AddFeature from './components/AddFeature'
import styles from './styles-common/layout.css'
import auth from './auth'
const appSection = document.createElement('div')
appSection.id = 'root'
document.body.insertBefore(appSection, document.body.firstChild);
function requireAuth(nextState, replace) {
  if (!auth.loggedIn()) {
    replace({
      pathname: '/login',
      state: { nextPathname: nextState.location.pathname }
    })
  }
}
ReactDom.render((
  <Router history={hashHistory}>
    <Route path="/" component={App} onEnter={requireAuth}>
      <IndexRoute component={Dashbord} />
      <Route path="request/:id" component={Request} />
      <Route path="/new-request" component={AddFeature} />
    </Route>
    <Route path="/login" component={Login} />
  </Router>
), appSection)

应用.jsx

import React from 'react'
import Header from '../Header'
import DropDownMenu from '../DropDownMenu'
import styles from './styles.css'
export default class App extends React.Component {
  render() {
    return (
      <div>
        <Header>
          <DropDownMenu />
        </Header>
        <div className={styles.contentContainer}>
          <main className={styles.content}>
            {this.props.children}
          </main>
        </div>
      </div>
    )
  }
}

身份验证.js

import request from 'superagent'
export default {
  login(email, pass, cb) {
    cb = arguments[arguments.length - 1]
    if (localStorage.token) {
      if (cb) cb(true)
      this.onChange(true)
      return
    }
    authenticate(email, pass, (res) => {
      if (res.authenticated) {
        localStorage.token = res.token
        localStorage.user_firstname = res.user_firstname
        localStorage.user_lastname = res.user_lastname
        localStorage.user_id = res.user_id
        if (cb) cb(true)
        this.onChange(true)
      } else {
        if (cb) cb(false)
        this.onChange(false)
      }
    })
  },
  getToken() {
    return localStorage.token
  },
  logout(cb) {
    delete localStorage.token
    if (cb) cb()
    this.onChange(false)
  },
  loggedIn() {
    return !!localStorage.token
  },
  onChange() {}
}
function authenticate (email, pass, callback) {
  let body = {email: email, password: pass}
  request
    .post('api/auth')
    .send(body)
    .end((err, res) => {
      let result = JSON.parse(res.text)
      if (result.success) {
        callback({
          authenticated: true,
          user_id: result.user_id,
          user_firstname: result.user_firstname,
          user_lastname: result.user_lastname,
          token: result.token
        })
      } else {
        callback({ authenticated: false} )
      }
  })
}

我的解决方案

身份验证.js

import request from 'superagent'
export default {
  login(email, pass, cb) {
    cb = arguments[arguments.length - 1]
    if (localStorage.token && this.activeUser()) {
      if (cb) cb(true)
      this.onChange(true)
      return
    }
    authenticate(email, pass, (res) => {
      if (res.authenticated) {
        localStorage.token = res.token
        localStorage.user_firstname = res.user_firstname
        localStorage.user_lastname = res.user_lastname
        localStorage.user_id = res.user_id
        localStorage.last_active = Date.now() // <--------------
        if (cb) cb(true)
        this.onChange(true)
      } else {
        if (cb) cb(false)
        this.onChange(false)
      }
    })
  },
  getToken() {
    return localStorage.token
  },
  logout(cb) {
    delete localStorage.token
    delete localStorage.user_firstname
    delete localStorage.user_lastname
    delete localStorage.user_id
    delete localStorage.last_active
    if (cb) cb()
    this.onChange(false)
  },
  // *--- Added this method ---*
  activeUser() {
    let i = parseInt(localStorage.last_active)
    return (
      localStorage.last_active &&
      (i + 3600000) >= Date.now() ?
      localStorage.last_active = Date.now() :
      false
    )
  },

  loggedIn() {
    return !!localStorage.token
  },
//...

索引.jsx

//...
function requireAuth(nextState, replace) {
  if (!auth.loggedIn() || !auth.activeUser()) {  // <--- Validate active 
    replace({
      pathname: '/login',
      state: { nextPathname: nextState.location.pathname }
    })
  }
}
//...

最新更新