我正在寻找一种有效的方法来防止未经授权的人访问特定的路由路径。
我从后端获得的cookie不可读,所以我不能用它做太多事情。 我有两个端点:
- /token (POST) 使用 token 获取 cookie
- /account (GET) 获取用户名和角色
对我到目前为止所做的事情的简短解释:
- 通过使用 PrivateRoute 组件包装所有路由来保护它们
- 用户尝试登录后会触发 redux 操作。此操作调用一个 api,该 API 返回 cookie (jwt) 和用户数据。用户名和角色将保存到“authStore”中。如果登录成功,同一商店中的属性“isAuthenticated”将设置为 True。只有当该 bool 值设置为 true 时,用户才能访问包装的路由。
我的问题:
如果我关闭标签页并打开一个新标签页,商店就会重置(这是正常现象)。不过,cookie 仍然可用。因此,为了获得良好的用户体验,我想直接对用户进行身份验证。此时用户被重定向到登录页面。这是有道理的,因为只有当 store 属性 isAuthenticated 为 true 时才能访问 PrivateRoute 组件。因此用户必须重新登录才能更新商店。
我尝试从方法 componentDidMount 中调度 App.js 中的操作以直接获取用户凭据,但这没有帮助。由于 render() 首先被触发,因此没有帮助。
这是我的代码:
应用程序.js:
export class App extends PureComponent {
componentDidMount() {
// Action to retrieve user credentials (if available then saves it to the authStore and sets isAuthenticated to true)
this.props.initloginRequest();
}
render() {
return (
<div className="d-flex flex-column h-100 w-100 bg-grey main-container">
<Sprites className="d-none" />
<Router>
<Header />
<Switch>
<Route path="/login" exact component={X1} />
<PrivateRoute path="/" exact component={X2} />
<PrivateRoute path="/details" exact component={X3} />
<PrivateRoute path="/finish" exact component={X4} />
</Switch>
</Router>
</div>
);
}
}
export class PrivateRoute extends Component {
render() {
const { isAuthenticated, component, ...rest } = this.props;
const renderComponent = (props) => {
if (isAuthenticated) {
const ComponentToShow = component;
return <ComponentToShow {...props} />
} else {
return <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
}
};
return (
<Route
{...rest}
render={renderComponent}
/>
)
}
}
export default connect(
(state) => ({
isAuthenticated: state.authStore.isAuthenticated
})
)(PrivateRoute);
有一个可能的解决方案,即根据/account 返回的状态代码进行 api 调用。每当路线改变时,就会调用电话,所以这并不是我真正想要的。我只想要一个需要在应用程序开始时进行一次调用的解决方案。
提前致谢
最佳答案
我通过在index.js(src路径)中分派(dispatch)一个操作解决了这个问题:
import './index.css';
import App from './App';
import { initloginRequest } from './actions/auth';
const store = configureStore();
store.dispatch(initloginRequest())
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById('root'),
);
此操作调用 api 并检查用户是否已通过身份验证。因此,当它到达我的 PrivateRoute 组件时,它知道应该将用户重定向到哪个方向。
您应该将 store/state 中的 isFetching 设置为 true,直到操作完成,以防止 App.js 渲染您的路线。
export class App extends PureComponent {
render() {
const { isFetching } = this.props
if (isFetching) {
return <div>Loading application...</div>
}
return (
<div className="d-flex flex-column h-100 w-100 bg-grey main-container">
<Sprites className="d-none" />
<Header />
<Switch>
...private route etc...
</Switch>
</div>
);
}
}
export default connect(
(state) => ({
isFetching: state.authStore.isFetching,
}),
(dispatch) => bindActionCreators({
}, dispatch),
)(App);
这应该可以解决问题。
关于reactjs - 当 session (存储的cookie)不可访问时如何保护 react 路由?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59415656/