如何使用 react-router 处理身份验证?
How to handle Authentication with react-router?
正在尝试使某些路由需要身份验证。
我有这个:
class App extends Component {
render() {
const menuClass = `${this.props.contentMenuClass} col-xs-12 col-md-9`;
return (
<BrowserRouter history={browserHistory}>
<div className="App">
<Header properties={this.props} />
<div className="container-fluid">
<div className="row">
<SideNav />
<div className={menuClass} id="mainContent">
<Switch>
{routes.map(prop =>
(
<Route
path={prop.path}
component={prop.component}
key={prop.id}
render={() => (
!AuthenticationService.IsAutheenticated() ?
<Redirect to="/Login"/>
:
<Route path={prop.path}
component={prop.component}
key={prop.id}/>
)}
/>
))}
</Switch>
</div>
</div>
</div>
{/* <Footer /> */}
</div>
</BrowserRouter>
);
}
}
const mapStateToProps = state => ({
contentMenuClass: state.menu,
});
export default connect(mapStateToProps)(App);
注意:是的,授权服务可以正常工作。
对于我正在检查用户是否经过身份验证的每条路线,如果没有,我想将他们重定向到登录页面,如果是,那么它将以“/”的路线登陆第一页。
我得到的是:
react-dom.development.js:14227 The above error occurred in the <Route> component:
in Route (created by App)
in Switch (created by App)
in div (created by App)
in div (created by App)
in div (created by App)
in div (created by App)
in Router (created by BrowserRouter)
in BrowserRouter (created by App)
in App (created by Connect(App))
in Connect(App)
in Provider
我哪里做错了?
你拼写 Autheenticated
错误。
此外,这是一个假设,因为您只提供了堆栈跟踪而不是 above error
,这可能表明 AuthenticationService.IsAutheenticated
不是函数。
一个简单的解决方案是制作一个 HOC
(高阶组件)来包装所有受保护的路由。
根据您的应用的嵌套程度,您可能希望使用本地状态或 redux
状态。
工作示例:https://codesandbox.io/s/5m2690nn6n(使用本地状态)
routes/index.js
import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "../components/Home";
import Players from "../components/Players";
import Schedule from "../components/Schedule";
import RequireAuth from "../components/RequireAuth";
export default () => (
<BrowserRouter>
<RequireAuth>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/players" component={Players} />
<Route path="/schedule" component={Schedule} />
</Switch>
</RequireAuth>
</BrowserRouter>
);
components/RequireAuth.js
import React, { Component, Fragment } from "react";
import { withRouter } from "react-router-dom";
import Login from "./Login";
import Header from "./Header";
class RequireAuth extends Component {
state = { isAuthenticated: false };
componentDidMount = () => {
if (!this.state.isAuthenticated) {
this.props.history.push("/");
}
};
componentDidUpdate = (prevProps, prevState) => {
if (
this.props.location.pathname !== prevProps.location.pathname &&
!this.state.isAuthenticated
) {
this.props.history.push("/");
}
};
isAuthed = () => this.setState({ isAuthenticated: true });
unAuth = () => this.setState({ isAuthenticated: false });
render = () =>
!this.state.isAuthenticated ? (
<Login isAuthed={this.isAuthed} />
) : (
<Fragment>
<Header unAuth={this.unAuth} />
{this.props.children}
</Fragment>
);
}
export default withRouter(RequireAuth);
或者,您可以创建一个包含受保护路由的受保护组件,而不是包装路由。
工作示例:https://codesandbox.io/s/yqo75n896x(使用 redux
而不是本地状态)。
routes/index.js
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import Home from "../components/Home";
import Header from "../containers/Header";
import Info from "../components/Info";
import Sponsors from "../components/Sponsors";
import Signin from "../containers/Signin";
import RequireAuth from "../containers/RequireAuth";
import rootReducer from "../reducers";
const store = createStore(rootReducer);
export default () => (
<Provider store={store}>
<BrowserRouter>
<div>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/info" component={Info} />
<Route path="/sponsors" component={Sponsors} />
<Route path="/protected" component={RequireAuth} />
<Route path="/signin" component={Signin} />
</Switch>
</div>
</BrowserRouter>
</Provider>
);
containers/RequireAuth.js
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import ShowPlayerRoster from "../components/ShowPlayerRoster";
import ShowPlayerStats from "../components/ShowPlayerStats";
import Schedule from "../components/Schedule";
const RequireAuth = ({ match: { path }, isAuthenticated }) =>
!isAuthenticated ? (
<Redirect to="/signin" />
) : (
<div>
<Route exact path={`${path}/roster`} component={ShowPlayerRoster} />
<Route path={`${path}/roster/:id`} component={ShowPlayerStats} />
<Route path={`${path}/schedule`} component={Schedule} />
</div>
);
export default connect(state => ({
isAuthenticated: state.auth.isAuthenticated
}))(RequireAuth);
您甚至可以通过创建包装函数来获得更多模块化。您可以通过简单地包裹组件来挑选和选择任何路线。我没有代码框示例,但它类似于 .
例如:<Route path="/blog" component={RequireAuth(Blog)} />
正在尝试使某些路由需要身份验证。
我有这个:
class App extends Component {
render() {
const menuClass = `${this.props.contentMenuClass} col-xs-12 col-md-9`;
return (
<BrowserRouter history={browserHistory}>
<div className="App">
<Header properties={this.props} />
<div className="container-fluid">
<div className="row">
<SideNav />
<div className={menuClass} id="mainContent">
<Switch>
{routes.map(prop =>
(
<Route
path={prop.path}
component={prop.component}
key={prop.id}
render={() => (
!AuthenticationService.IsAutheenticated() ?
<Redirect to="/Login"/>
:
<Route path={prop.path}
component={prop.component}
key={prop.id}/>
)}
/>
))}
</Switch>
</div>
</div>
</div>
{/* <Footer /> */}
</div>
</BrowserRouter>
);
}
}
const mapStateToProps = state => ({
contentMenuClass: state.menu,
});
export default connect(mapStateToProps)(App);
注意:是的,授权服务可以正常工作。
对于我正在检查用户是否经过身份验证的每条路线,如果没有,我想将他们重定向到登录页面,如果是,那么它将以“/”的路线登陆第一页。
我得到的是:
react-dom.development.js:14227 The above error occurred in the <Route> component: in Route (created by App) in Switch (created by App) in div (created by App) in div (created by App) in div (created by App) in div (created by App) in Router (created by BrowserRouter) in BrowserRouter (created by App) in App (created by Connect(App)) in Connect(App) in Provider
我哪里做错了?
你拼写 Autheenticated
错误。
此外,这是一个假设,因为您只提供了堆栈跟踪而不是 above error
,这可能表明 AuthenticationService.IsAutheenticated
不是函数。
一个简单的解决方案是制作一个 HOC
(高阶组件)来包装所有受保护的路由。
根据您的应用的嵌套程度,您可能希望使用本地状态或 redux
状态。
工作示例:https://codesandbox.io/s/5m2690nn6n(使用本地状态)
routes/index.js
import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "../components/Home";
import Players from "../components/Players";
import Schedule from "../components/Schedule";
import RequireAuth from "../components/RequireAuth";
export default () => (
<BrowserRouter>
<RequireAuth>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/players" component={Players} />
<Route path="/schedule" component={Schedule} />
</Switch>
</RequireAuth>
</BrowserRouter>
);
components/RequireAuth.js
import React, { Component, Fragment } from "react";
import { withRouter } from "react-router-dom";
import Login from "./Login";
import Header from "./Header";
class RequireAuth extends Component {
state = { isAuthenticated: false };
componentDidMount = () => {
if (!this.state.isAuthenticated) {
this.props.history.push("/");
}
};
componentDidUpdate = (prevProps, prevState) => {
if (
this.props.location.pathname !== prevProps.location.pathname &&
!this.state.isAuthenticated
) {
this.props.history.push("/");
}
};
isAuthed = () => this.setState({ isAuthenticated: true });
unAuth = () => this.setState({ isAuthenticated: false });
render = () =>
!this.state.isAuthenticated ? (
<Login isAuthed={this.isAuthed} />
) : (
<Fragment>
<Header unAuth={this.unAuth} />
{this.props.children}
</Fragment>
);
}
export default withRouter(RequireAuth);
或者,您可以创建一个包含受保护路由的受保护组件,而不是包装路由。
工作示例:https://codesandbox.io/s/yqo75n896x(使用 redux
而不是本地状态)。
routes/index.js
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import Home from "../components/Home";
import Header from "../containers/Header";
import Info from "../components/Info";
import Sponsors from "../components/Sponsors";
import Signin from "../containers/Signin";
import RequireAuth from "../containers/RequireAuth";
import rootReducer from "../reducers";
const store = createStore(rootReducer);
export default () => (
<Provider store={store}>
<BrowserRouter>
<div>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/info" component={Info} />
<Route path="/sponsors" component={Sponsors} />
<Route path="/protected" component={RequireAuth} />
<Route path="/signin" component={Signin} />
</Switch>
</div>
</BrowserRouter>
</Provider>
);
containers/RequireAuth.js
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import ShowPlayerRoster from "../components/ShowPlayerRoster";
import ShowPlayerStats from "../components/ShowPlayerStats";
import Schedule from "../components/Schedule";
const RequireAuth = ({ match: { path }, isAuthenticated }) =>
!isAuthenticated ? (
<Redirect to="/signin" />
) : (
<div>
<Route exact path={`${path}/roster`} component={ShowPlayerRoster} />
<Route path={`${path}/roster/:id`} component={ShowPlayerStats} />
<Route path={`${path}/schedule`} component={Schedule} />
</div>
);
export default connect(state => ({
isAuthenticated: state.auth.isAuthenticated
}))(RequireAuth);
您甚至可以通过创建包装函数来获得更多模块化。您可以通过简单地包裹组件来挑选和选择任何路线。我没有代码框示例,但它类似于
例如:<Route path="/blog" component={RequireAuth(Blog)} />