Javascript 如何在react路由器中限制对路由的访问?

Javascript 如何在react路由器中限制对路由的访问?,javascript,reactjs,react-router,Javascript,Reactjs,React Router,有人知道如何限制对react路由器中特定路由的访问吗?在允许访问特定路由之前,我想检查用户是否已登录。我以为这会很简单,但医生们不清楚怎么做 这是我应该在定义组件的地方设置的,还是应该在组件处理程序中处理 <Route handler={App} path="/"> <NotFoundRoute handler={NotFound} name="not-found"/> <DefaultRoute handler={Login} name="login"/&

有人知道如何限制对react路由器中特定路由的访问吗?在允许访问特定路由之前,我想检查用户是否已登录。我以为这会很简单,但医生们不清楚怎么做

这是我应该在定义
组件的地方设置的,还是应该在组件处理程序中处理

<Route handler={App} path="/">
  <NotFoundRoute handler={NotFound} name="not-found"/>
  <DefaultRoute handler={Login} name="login"/>
  <Route handler={Todos} name="todos"/> {/* I want this to be restricted */}
</Route>

{/*我想限制它*/}

通常,登录用户将被授予令牌,并将该令牌用于与服务器的任何通信。我们通常做的是定义一个根页面,然后在该页面上构建内容。此根页面为您执行本地化、身份验证和其他配置

这里有一个例子

Routes = (
    <Route path="/" handler={Root}>
        <Route name="login" handler={Login} />
        <Route name="forget" handler={ForgetPassword} />
        <Route handler={Main} >
            <Route name="overview" handler={Overview} />
            <Route name="profile" handler={Profile} />
            <DefaultRoute handler={Overview} />
        </Route>
        <DefaultRoute handler={Login} />
        <NotFoundRoute handler={NotFound} />
    </Route>
);
Routes=(
);
在您的根页面上,检查令牌null或向服务器验证令牌,以查看用户是否有效登录


希望这有帮助:)

如果您想在整个应用程序中使用身份验证,您需要在应用程序范围内存储一些数据(例如令牌)。您可以设置两个React mixin,它们负责管理
$auth
对象。这个对象不应该在这两个mixin之外可用。下面是一个例子:

define('userManagement', function() {
    'use strict';

    var $auth = {
        isLoggedIn: function () {
            // return something, e.g. using server-stored data
        }
    };

    return {
        Authenticator: {
           login: function(username, password) {
               // modify $auth object, or call server, or both
           }
        },

        NeedsAuthenticatedUser: {
            statics: {
                willTransitionTo: function (transition) {
                    if (!$auth.isLoggedIn()) {
                        transition.abort();
                    }
                }
            }
        }
    };
});
然后,您可以将
Authenticator
混合到您的登录组件(登录屏幕、登录弹出窗口等)中,并在获得所有必要数据后调用
this.login
函数

最重要的是通过混合
NeedsAuthenticatedUser
mixin来保护组件。每个需要经过身份验证的用户的组件必须如下所示:

var um = require('userManagement');

var ProtectedComponent = React.createClass({
    mixins: [um.NeedsAuthenticatedUser]
    // ...
}
请注意,
NeedsAuthenticatedUser
使用react路由器API(
willtransitionon
transition.abort()
)。

更新(2019年8月16日) 在react router v4和使用react挂钩时,这看起来有点不同。让我们从你的
App.js
开始

导出默认函数App(){
const[isAuthenticated,userHasAuthenticated]=useState(false);
useffect(()=>{
onLoad();
}, []);
异步函数onLoad(){
试一试{
等待Auth.currentSession();
userHasAuthenticated(true);
}捕获(e){
警报(e);
}
}
返回(
欢迎使用我的应用程序

旧版本 公认的答案是正确的,但React团队认为混入有害()

如果有人遇到这个问题,并且正在寻找推荐的方法,我建议使用高阶组件而不是mixin

下面是一个HOC示例,它将在继续操作之前检查用户是否登录。如果用户未登录,则它将重定向到登录页面。此组件采用一个名为
isLoggedIn
的道具,它基本上是应用程序可以存储的一个标志,用于指示用户是否登录

从“React”导入React;
从“react router”导入{withRouter};
导出默认函数requireAuth(组件){
类AuthenticatedComponent扩展了React.Component{
组件willmount(){
this.checkAuth();
}
checkAuth(){
如果(!this.props.isLoggedIn){
const location=this.props.location;
const redirect=location.pathname+location.search;
this.props.router.push(`/login?redirect=${redirect}`);
}
}
render(){
返回此.props.isLoggedIn
? 
:null;
}
}
返回路由器(认证组件);
}
要使用这个HOC,只需将它环绕在您的路线上。对于您的示例,它将是:

<Route handler={requireAuth(Todos)} name="todos"/>


我在一个详细的分步教程中介绍了这一点和其他一些主题-

react router
鼓励对路由器采用声明式方法,您应该使路由器尽可能哑,并避免将路由逻辑放入组件中

下面是您可以执行此操作的方法(假设您将
loggedIn
prop传递给它):

const DumbRouter=({loggedIn})=>(
{[
!loggedIn&&loggedoutrotes,
loggedIn&&LoggedInRouter,
]}
);
常数LoggedInRoutes=[
];
常数对数对数=[
];
在React Router 4的文档中(现在?)有一个这样的例子

从'react router'导入{Route,Redirect}
(
洛格丁(
) : (
)
)}/>
private-route.tsx

从'react router'导入{Redirect,Route,RouteProps};
从“React”导入*作为React;
接口PrivateRouteProps扩展了RouteProps{
/**
*例如“/login”。
*/
重定向到:字符串;
/**
*如果为true,则不会重定向。
*我们使用的是函数而不是bool,bool似乎没有更新
*在成功认证之后。
*/
isLogged:()=>布尔值;
}
导出函数PrivateRoute(道具:PrivateRoutes道具){
//`component:component`未键入,它将值分配给新变量。
让{isloged,redirectTo,component:component,…rest}:any=props;
//错误:JSX类型元素组件没有调用签名或…通过添加任何仍在工作的,
//没有找到一个合适的方法来修复它。
返回(
isLogged()
? 
: 
)} />;
}
用法:

        <PrivateRoute exact={true} 
                      path="/admin/" 
                      redirectTo={'/admin/login'} 
                      isLogged={this.loginService.isLogged} 
                      component={AdminDashboardPage}/>
        <Route path="/admin/login/" component={AdminLoginPage}/>


基于。

您可以使用HOC,auth是一个变量,您可以更改值true或false表示(授权)


(auth?():())}/>

您可以避免在确认身份验证之前呈现组件,如下所示:

import { useState, useEffect, useRef } from 'react';
import { useHistory } from 'react-router-dom';

const Route = () => {
    const [loading, sertLoading] = useState(true);
    const history = useHistory();

    const ref = useRef<Function>({});

    // must use ref!
    ref.current.routeGuard = () => {
        const authenticationHandler = (): boolean => {
         // do authentication here
        }
        sertLoading(true);
        const go = authenticationHandler();
        if (go === false) {
            history.goBack();
        }
        sertLoading(false);
    } 

    useEffect(() => {
        ref.current.routeGuard();
        history.listen(() => {
            ref.current.routeGuard();
        });
    }, []);

    return (
        <>
            {!loading && <YourRouteComponent />}
        </>
    )
};
从'react'导入{useState,useffect,useRef};
从'react router dom'导入{useHistory};
常数路由=()=>{
const[loading,sertLoading]=使用状态(true);
const history=useHistory();
const ref=useRef({});
//必须使用ref!
ref.current.routeGuard=()=>{
有限公司
import {Redirect, Route, RouteProps} from 'react-router';
import * as React from 'react';

interface PrivateRouteProps extends RouteProps {
  /**
   * '/login' for example.
   */
  redirectTo: string;

  /**
   * If true, won't redirect.
   * We are using a function instead of a bool, a bool does not seem to be updated
   * after having successfully authenticated.
   */
  isLogged: () => boolean;
}


export function PrivateRoute(props: PrivateRouteProps) {
  // `component: Component` is not typing, it assign the value to a new variable.
  let { isLogged, redirectTo, component: Component, ...rest }: any = props;

  // error: JSX type element Component does not have call signature or ... AVOIDED BY ADDING ANY, still work,
  // and did not find a proper way to fix it.
  return <Route {...rest} render={(props) => (
    isLogged()
      ? <Component {...props}/>
      : <Redirect to={{
        pathname: redirectTo,
        state: { from: props.location }
      }} />
  )} />;
}
        <PrivateRoute exact={true} 
                      path="/admin/" 
                      redirectTo={'/admin/login'} 
                      isLogged={this.loginService.isLogged} 
                      component={AdminDashboardPage}/>
        <Route path="/admin/login/" component={AdminLoginPage}/>
<Route path="/login" component={SignIn} />
<Route path="/posts" render = {() => (auth ?  (<Post />) : (<Redirect to="/login" />))}/>
import { useState, useEffect, useRef } from 'react';
import { useHistory } from 'react-router-dom';

const Route = () => {
    const [loading, sertLoading] = useState(true);
    const history = useHistory();

    const ref = useRef<Function>({});

    // must use ref!
    ref.current.routeGuard = () => {
        const authenticationHandler = (): boolean => {
         // do authentication here
        }
        sertLoading(true);
        const go = authenticationHandler();
        if (go === false) {
            history.goBack();
        }
        sertLoading(false);
    } 

    useEffect(() => {
        ref.current.routeGuard();
        history.listen(() => {
            ref.current.routeGuard();
        });
    }, []);

    return (
        <>
            {!loading && <YourRouteComponent />}
        </>
    )
};