Javascript 如何限制对反应路由器中路由的访问?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31084779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to restrict access to routes in react-router?
提问by Tanner Semerad
Does anyone know how to restrict access to particular routes in react-router? I want to check if the user is logged in before allowing access to a particular route. I thought it would be simple, but the docs aren't clear how to do it.
有谁知道如何限制对 react-router 中特定路由的访问?我想在允许访问特定路线之前检查用户是否已登录。我认为这很简单,但文档不清楚如何去做。
Is this something I should set up where I define my <Route>
components, or should I be handling it inside my component handlers?
这是我应该在定义<Route>
组件的地方设置的东西,还是应该在我的组件处理程序中处理它?
<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>
回答by jayair
Update (Aug 16, 2019)
更新(2019 年 8 月 16 日)
In react-router v4 and using React Hooks this looks a little different. Let's start with your App.js
.
在 react-router v4 和使用 React Hooks 中,这看起来有点不同。让我们从您的App.js
.
export default function App() {
const [isAuthenticated, userHasAuthenticated] = useState(false);
useEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
await Auth.currentSession();
userHasAuthenticated(true);
} catch (e) {
alert(e);
}
}
return (
<div className="App container">
<h1>Welcome to my app</h1>
<Switch>
<UnauthenticatedRoute
path="/login"
component={Login}
appProps={{ isAuthenticated }}
/>
<AuthenticatedRoute
path="/todos"
component={Todos}
appProps={{ isAuthenticated }}
/>
<Route component={NotFound} />
</Switch>
</div>
);
}
We are using an Auth
library to check if the user is currently authenticated. Replace this with your auth check function. If so then we set the isAuthenticated
flag to true
. We do this when our App first loads. Also worth mentioning, you might want to add a loading sign on your app while the auth check is being run, so you don't flash the login page every time you refresh the page.
我们正在使用一个Auth
库来检查用户当前是否已通过身份验证。将其替换为您的身份验证检查功能。如果是这样,那么我们将isAuthenticated
标志设置为true
。我们在应用程序首次加载时执行此操作。另外值得一提的是,您可能希望在运行身份验证检查时在您的应用程序上添加一个加载标志,这样您就不会在每次刷新页面时都刷新登录页面。
Then we pass the flag to our routes. We create two type of routes AuthenticatedRoute
and UnauthenticatedRoute
.
然后我们将标志传递给我们的路线。我们创建了两种类型的路由AuthenticatedRoute
和UnauthenticatedRoute
。
The AuthenticatedRoute.js
looks like this.
长AuthenticatedRoute.js
这样。
export default function AuthenticatedRoute({ component: C, appProps, ...rest }) {
return (
<Route
{...rest}
render={props =>
appProps.isAuthenticated
? <C {...props} {...appProps} />
: <Redirect
to={`/login?redirect=${props.location.pathname}${props.location.search}`}
/>}
/>
);
}
It checks if isAuthenticated
is set to true
. If it is, then it'll render the desired component. If not, then it'll redirect to the login page.
它检查是否isAuthenticated
设置为true
。如果是,那么它将呈现所需的组件。如果没有,那么它将重定向到登录页面。
The UnauthenticatedRoute.js
on the other hand looks like this.
在UnauthenticatedRoute.js
另一方面,看起来是这样的。
export default ({ component: C, appProps, ...rest }) =>
<Route
{...rest}
render={props =>
!appProps.isAuthenticated
? <C {...props} {...appProps} />
: <Redirect to="/" />}
/>;
In this case, if the isAuthenticated
is set to false
, it'll render the desired component. And if it is set to true, it'll send you to the homepage.
在这种情况下,如果isAuthenticated
设置为false
,它将呈现所需的组件。如果它设置为 true,它会将您发送到主页。
You can find detailed versions of this on our guide - https://serverless-stack.com/chapters/create-a-route-that-redirects.html.
您可以在我们的指南中找到详细版本 - https://serverless-stack.com/chapters/create-a-route-that-redirects.html。
Older version
旧版本
The accepted answer is correct but Mixins are considered to be harmful (https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html) by the React team.
接受的答案是正确的,但React 团队认为 Mixins 是有害的(https://facebook.github.io/react/blog/2016/07/13/mixins-thinked-harmful.html)。
If somebody comes across this question and is looking for the recommended way to do this, I'd suggest using Higher Order Components instead of Mixins.
如果有人遇到这个问题并正在寻找推荐的方法来做到这一点,我建议使用高阶组件而不是 Mixins。
Here is an example of a HOC that'll check if the user is logged in before proceeding. And if the user is not logged in, then it'll redirect you to the login page. This component takes a prop called isLoggedIn
, that is basically a flag that your application can store to denote if the user is logged in.
这是一个 HOC 的示例,它将在继续之前检查用户是否已登录。如果用户未登录,那么它会将您重定向到登录页面。该组件采用一个名为 的道具isLoggedIn
,这基本上是您的应用程序可以存储的一个标志,用于表示用户是否已登录。
import React from 'react';
import { withRouter } from 'react-router';
export default function requireAuth(Component) {
class AuthenticatedComponent extends React.Component {
componentWillMount() {
this.checkAuth();
}
checkAuth() {
if ( ! this.props.isLoggedIn) {
const location = this.props.location;
const redirect = location.pathname + location.search;
this.props.router.push(`/login?redirect=${redirect}`);
}
}
render() {
return this.props.isLoggedIn
? <Component { ...this.props } />
: null;
}
}
return withRouter(AuthenticatedComponent);
}
And to use this HOC, just wrap it around your routes. In case of your example, it would be:
要使用这个 HOC,只需将它包裹在你的路线上。在您的示例中,它将是:
<Route handler={requireAuth(Todos)} name="todos"/>
I cover this and a few other topics in a detailed step-by-step tutorial here - https://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html
我在这里的详细分步教程中介绍了这个和其他一些主题 - https://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html
回答by jacob
回答by Micha? P?achta
If you want to use authentication across your whole application, you need to store some data application-wide (e.g. token). You can set up two React mixins that are responsible for managing $auth
object. This object shouldn't be available outside those two mixins. Here's example of that:
如果要在整个应用程序中使用身份验证,则需要在应用程序范围内存储一些数据(例如令牌)。您可以设置两个负责管理$auth
对象的React mixin 。该对象不应该在这两个 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();
}
}
}
}
};
});
Then you can just mixin Authenticator
mixing to your login components (login screen, login popup, etc) and call this.login
function when you have all the data necessary.
然后,您可以将 mixinAuthenticator
混合到您的登录组件(登录屏幕、登录弹出窗口等)并this.login
在您拥有所有必要的数据时调用函数。
The most important thing is protecting your components by mixing in NeedsAuthenticatedUser
mixin. Each component that needs authenticated user will have to look like that:
最重要的是通过混入NeedsAuthenticatedUser
mixin来保护你的组件。每个需要经过身份验证的用户的组件都必须如下所示:
var um = require('userManagement');
var ProtectedComponent = React.createClass({
mixins: [um.NeedsAuthenticatedUser]
// ...
}
Note that NeedsAuthenticatedUser
uses react-router API (willTransitionTo
and transition.abort()
).
请注意,NeedsAuthenticatedUser
使用 react-router API (willTransitionTo
和transition.abort()
)。
回答by gwendall
react-router
encourages a declarative approach for your router, you should make your router as dumb as possible and avoid putting your routing logic in your components.
react-router
鼓励为您的路由器采用声明式方法,您应该使您的路由器尽可能愚蠢并避免将您的路由逻辑放在您的组件中。
Here is how you can do it (assuming you pass it the loggedIn
prop):
以下是您可以这样做的方法(假设您将loggedIn
道具传递给它):
const DumbRouter = ({ loggedIn }) => (
<Router history={history}>
<Switch>
{[
!loggedIn && LoggedOutRoutes,
loggedIn && LoggedInRouter,
<Route component={404Route} />
]}
</Switch>
</Router>
);
const LoggedInRoutes = [
<Route path="/" component={Profile} />
];
const LoggedOutRoutes = [
<Route path="/" component={Login} />
];
回答by Ambroise Rabier
private-route.tsx
私有路由.tsx
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 }
}} />
)} />;
}
Usage:
用法:
<PrivateRoute exact={true}
path="/admin/"
redirectTo={'/admin/login'}
isLogged={this.loginService.isLogged}
component={AdminDashboardPage}/>
<Route path="/admin/login/" component={AdminLoginPage}/>
Based on https://tylermcginnis.com/react-router-protected-routes-authentication/.
基于https://tylermcginnis.com/react-router-protected-routes-authentication/。
回答by Ankit Kumar Rajpoot
You can use HOC and auth is a variable you can change value true or false means(authorization)
您可以使用 HOC 并且 auth 是一个变量,您可以更改值 true 或 false 表示(授权)
<Route path="/login" component={SignIn} />
<Route path="/posts" render = {() => (auth ? (<Post />) : (<Redirect to="/login" />))}/>
回答by Jim
usually a logged in user will be granted a token, and uses this token for any communication with server. What we usually do is define a root page, and things build on top of that page. this root page does localisation, authentication and other configurations for you.
通常,登录用户将被授予一个令牌,并使用此令牌与服务器进行任何通信。我们通常做的是定义一个根页面,然后建立在该页面之上。此根页面为您进行本地化、身份验证和其他配置。
here's an example
这是一个例子
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>
);
on your root page, check for token null or authenticate the token with server to see if user is valid login.
在您的根页面上,检查令牌是否为空或使用服务器验证令牌以查看用户是否有效登录。
hope this helps :)
希望这可以帮助 :)