React 路由授权

66

在组件挂载之前,授权检查的最佳实践是什么?

我使用 react-router 1.x

以下是我的路由:

React.render((
  <Router history={History.createHistory()}>
    <Route path="/" component={Dashboard}></Route>
    <Route path="/login" component={LoginForm}></Route>
  </Router>
), document.body);

这是我的仪表板组件:

var Dashboard = React.createClass({
  componentWillMount: function () {
    // I want to check authorization here
    // If the user is not authorized they should be redirected to the login page.
    // What is the right way to perform this check?
  },

  render: function () {
    return (
      <h1>Welcome</h1>
    );
  }
});

3
你是如何进行检查的呢?通过 cookie 吗?还是通过服务器调用?我认为通常是在 RouteonEnter 中完成,而不是在 componentWillMount 中。 <Route path='/' component={Dashboard} onEnter={function(nextState, transition) { if (!USER_IS_AUTHED) { transition.to('login'); }}) - Dylan
3个回答

71

更新React路由器v4的解决方案

<Route 
  path="/some-path" 
  render={() => !isAuthenticated ?
    <Login/> :
    <Redirect to="/some-path" />
}/>

React Router 版本3及以下

使用 'onEnter' 事件,在回调函数中检查用户是否已授权:

<Route path="/" component={App} onEnter={someAuthCheck}>  

const someAuthCheck = (nextState, transition) => { ... }

7
例子和文档方面情况变得更糟了。 "auth-flow" 的例子对我来说不起作用,并且很难找到有关处理程序的第二个参数应该接受什么内容的信息,以便我可以尝试不同的方法。 - backdesk
onEnter(nextState, replace, callback?)"当路由即将进入时调用。它提供了下一个路由状态和一个函数,用于重定向到另一个路径。这将是触发钩子的路由实例。" - backdesk
2
不,这不是一个好的解决方案。通常你会在状态中保存关于授权的信息。例如:'isAuth: true'。你可以将此变量作为属性传递到组件中,并在需要时自行传递。但是你无法将任何状态变量传递给“Route”。因此,你被迫从“Route”发出“fetch”调用、Ajax请求到服务器,以确定用户是否已登录。这是荒谬的和糟糕的设计,使用简单的状态变量并进行具有相同目的的Ajax请求。 - Green
2
@Green 这里可能有些混淆:您说应该使用状态信息。但是在 onEnter 函数中,您可以直接访问简单的状态变量(状态是函数的第一个参数),无需进行额外的 ajax 请求。 - Laurens Rietveld
3
对于从谷歌搜索而来的用户:onEnterreact-router-4 中已经不存在了。请参考:https://dev59.com/YlgQ5IYBdhLWcg3wcTeH - Alex Johnson
显示剩余3条评论

6
使用react-router 4,您可以在组件内部访问路由属性。要重定向用户,您只需将新的URL推送到历史记录中。在您的示例中,代码如下:
var Dashboard = React.createClass({
  componentWillMount: function () {
    const history = this.props.history; // you'll have this available
    // You have your user information, probably from the state
    // We let the user in only if the role is 'admin'
    if (user.role !== 'admin') {
      history.push('/'); // redirects the user to '/'
    }
  },

  render: function () {
    return (
      <h1>Welcome</h1>
    );
  }
});

在文档中,他们展示了另一种方法来实现它,通过使用render属性,而不是component。他们定义了一个PrivateRoute,当您定义所有路由时,代码非常明确。

-1
如果您想在多个组件上应用授权,则可以像这样操作。
<Route onEnter={requireAuth} component={Header}>
    <Route path='dashboard' component={Dashboard} />
    <Route path='events' component={Events} />
</Route>

对于单个组件,您可以执行以下操作

<Route onEnter={requireAuth} component={Header}/>

function requireAuth(nextState, replaceState) {
  if (token || or your any condition to pass login test)
  replaceState({ nextPathname: nextState.location.pathname }, 
  '/login')
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接