React Router auth-flow不会重定向无效/过期令牌

时间:2016-03-01 16:21:39

标签: authentication reactjs client-side react-router

我的问题

我正在关注react-router repo中的auth-flow example以进行客户端身份验证。

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

感谢您的帮助

代码

index.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)

App.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>
    )
  }
}

auth.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} )
      }
  })
}

1 个答案:

答案 0 :(得分:0)

我的解决方案

<强> auth.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
  },

//...

<强> index.jsx

//...

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

//...