如何在 React 应用程序中设置受保护的路由
构建 Web 应用时,某些路由可能涉及身份验证。您希望限制用户访问某些页面,或者希望整个应用都要求登录。
React Router是处理路由的绝佳选择,但你无法真正保护路由不被任何人访问。好在解决方案非常简单直接。
在本教程中,我将向您展示我针对这个问题的解决方案以及我是如何解决的。我将使用 create-react-app 从零开始,只包含绝对必要的内容,以便您能够跟上进度。事不宜迟,让我们开始编写代码吧。
设置一切
使用create-react-app引导项目后,我还安装了react-router-dom
路由。这个项目不需要任何其他依赖项。初始文件没有太多修改create-react-app
,这是文件的当前状态package.json
:
{
"name": "auth",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.4.0",
"@testing-library/user-event": "^7.2.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
+ "react-router-dom": "^5.1.2",
"react-scripts": "3.3.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
修改索引文件
我们将通过创建一个自定义组件来处理传入的请求,从而实现保护。我们Route
在 React 中有一个普通的旧组件。它将用于我们唯一的公共路由,即登录页面。我们还想创建一个自定义组件来处理私有路由。我们称之为ProtectedRoute
。
该组件的目的非常简单。如果用户已通过身份验证,则渲染传入的组件。否则,将其重定向到登录页面。
import React from 'react';
import ReactDOM from 'react-dom';
+ import { Route, BrowserRouter, Switch } from 'react-router-dom';
import './index.css';
+ import Login from './Login';
+ import Dashboard from './Dashboard';
+ import Settings from './Settings';
+ import ProtectedRoute from './ProtectedRoute';
import * as serviceWorker from './serviceWorker';
+ ReactDOM.render((
+ <BrowserRouter>
+ <Switch>
+ <Route path="/login" component={Login} />
+ <ProtectedRoute exact={true} path="/" component={Dashboard} />
+ <ProtectedRoute path="/settings" component={Settings} />
+ <ProtectedRoute component={Dashboard} />
+ </Switch>
+ </BrowserRouter>
+ ), document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
如您所见,我已经从 导入了、Route
和BrowserRoute
。我还创建了一些组件,以便我们可以测试路由器。Switch
react-router-dom
ProtectedRoute
将以下列方式运作:
- 它需要一个
component
prop,也就是它应该渲染的 prop - 它还需要一个路径,以便它知道在哪个 URL 上渲染哪个组件
这里我定义了Dashboard
两次组件。这是因为我们希望在没有定义路径的情况下直接跳转到 Dashboard。这就是第 15 行处理的事情。我们还希望在用户输入无效 URL 时加载 Dashboard。通过path
省略第 17 行的属性,我们告诉 React Router 回退到提供的组件。那么,让我们看看ProtectedRoute
组件内部是如何工作的。
创建受保护的路由
那么我们导入的自定义组件里面有什么呢?其实很简单,只有一个 render 函数:
import React from 'react'
import { Redirect } from 'react-router-dom'
class ProtectedRoute extends React.Component {
render() {
const Component = this.props.component;
const isAuthenticated = ???;
return isAuthenticated ? (
<Component />
) : (
<Redirect to={{ pathname: '/login' }} />
);
}
}
export default ProtectedRoute;
我们从 props 中获取组件,并在用户已通过身份验证后返回。我还使用了Redirect
from react-router-dom
。如果isAuthenticated
结果为 false,我们将用户重定向到登录页面。
那么我们究竟该如何判断用户是否通过了身份验证呢?我们应该将 赋值给 什么呢isAuthenticated
?
验证用户
最后一步是验证用户身份。验证方式多种多样,您的具体实现方式可能有所不同。我们可以使用 Cookie,或者localStorage
,或者两者结合,或者其他方式。无论哪种方式,我们都希望在客户端存储一些用户信息,以便了解用户何时登录。
render() {
const Component = this.props.component;
const isAuthenticated = localStorage.getItem('token');
return isAuthenticated ? (
<Component />
) : (
<Redirect to={{ pathname: '/login' }} />
);
}
为了防止伪造,此信息可能是令牌的存在与否,您也需要在服务器端验证该令牌。这样,您就可以确保用户无法仅凭密钥的存在就登录token
。这确保了密钥的值才是真正重要的。
正如您在上面的动图中所见,如果我刷新页面,它会带我到登录屏幕。如果我尝试访问任何其他有限制的路由,我会被重定向回登录页面。如果我设置了一个令牌——无论现在的值是什么——我都可以访问这些页面。另请注意,如果我在登录后尝试访问一个不存在的路由,我会进入仪表板。一旦我清除存储空间,我就会失去访问权限。
概括
总结一下:即使你的 React 代码库被混淆了,你的客户端应用程序的工作方式也可能被逆向工程。这就是为什么所有涉及身份验证或授权的操作都必须由服务器端实现进行备份。
感谢您花时间阅读,请在下方评论区分享您对此方法的看法。您的安全解决方案是什么?🔒
文章来源:https://dev.to/flowforfrank/how-to-set-up-protected-routes-in-your-react-application-h32