当用React构建SPA(单页面应用程序)时,路由是开发者必须处理的基本流程之一。React路由是建立路由的过程,确定路由的内容,并在认证和授权下确保其安全。有许多工具可用于管理和保护React中的路由。最常用的是react-router 。然而,许多开发人员不在可以使用react-router 库的情况下。正因为如此,他们可能需要使用Reach Router、Wouter,甚至可能根本就没有路由器。
本教程将告诉你如何使用React、Okta和Wouter快速构建一个安全的SPA。Okta可以让你轻松地管理对SPA(或任何应用程序)的访问。通过使用@okta/okta-react 库,你可以用React快速构建安全应用程序。在写这篇文章的时候,reach-router不支持React 17+版本。
先决条件:
目录
创建一个Okta OIDC应用程序
在你开始之前,你需要一个免费的Okta开发者账户。安装Okta CLI并运行okta register 来注册一个新账户。如果您已经有一个账户,运行okta login 。然后,运行okta apps create 。选择默认的应用程序名称,或根据你的需要进行更改。 选择单页应用程序,然后按回车键。
在重定向URI中使用http://localhost:3000/callback ,并将注销重定向URI设置为http://localhost:3000 。
Okta CLI是做什么的?
Okta CLI将在您的Okta机构中创建一个OIDC单页应用。它将添加您指定的重定向URI并授予Everyone组的访问权限。它还会为http://localhost:3000 添加一个受信任的来源。当它完成时,你会看到如下的输出。
Okta application configuration:
Issuer: https://dev-133337.okta.com/oauth2/default
Client ID: 0oab8eb55Kb9jdMIr5d6
注意:你也可以使用Okta管理控制台来创建你的应用程序。更多信息请参见创建一个React应用程序。
一旦Okta处理完您的请求,它将返回一个签发人和一个客户ID。确保你注意到这些,因为你将在你的应用程序中需要它们。
创建一个具有路由功能的React应用程序
接下来,打开你最喜欢的IDE(我使用Visual Studio Code),并使用任务运行器npx create-react-app react-routing-demo ,为你的React项目提供支架。你会被提示安装create-react-app 。键入y来批准。
这个过程需要一分钟,如果你愿意,可以拿杯咖啡或茶。任务运行器在快速启动你的应用程序方面做得很好,但你将需要添加和编辑一些文件。
在你开始之前,你将需要安装一些软件包。
首先,当然是wouter。
cd react-routing-demo
npm i wouter@2.7.5
你将使用Bootstrap以及react-bootstrap库来设计你的应用程序。
npm i bootstrap@5.1.3
npm i react-bootstrap@1.6.4
接下来,你将得到dotenv,作为存储Okta敏感信息的一种方式。
npm i dotenv@10.0.0
最后,你将把Okta React SDK添加到你的项目中。
npm i @okta/okta-react@6.2.0 @okta/okta-auth-js@5.6.0
安装了这些依赖项后,你可以开始创建你的应用程序。首先,在你的项目根部添加一个名为.env 的新文件,并添加以下项目。注意这里的REACT_APP_OKTA_ISSUER 应该与Okta CLI中的发行者相匹配。
REACT_APP_OKTA_CLIENTID={yourClientId}
REACT_APP_OKTA_APP_BASE_URL=http://localhost:3000
REACT_APP_OKTA_ISSUER=/oauth2/default
接下来,为Components 和Pages 添加一个文件夹。
mkdir src/Components
mkdir src/Pages
在Components ,为Header.jsx 添加一个新文件,并添加以下代码。
import React from "react";
import { Navbar, Nav, Form, Button } from "react-bootstrap";
const Header = ({ authState, oktaAuth }) => {
if (authState?.isPending) {
return <div>Loading...</div>;
}
const button = authState?.isAuthenticated ? (
<Button
variant="secondary"
onClick={() => {
oktaAuth.signOut("/");
}}
>
Logout
</Button>
) : (
<Button
variant="secondary"
onClick={() => {
oktaAuth.signInWithRedirect();
}}
>
Login
</Button>
);
return (
<Navbar bg="light" expand="lg">
<Navbar.Brand href="/">React Routing</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto"></Nav>
<Form inline>{button}</Form>
</Navbar.Collapse>
</Navbar>
);
};
export default Header;
这个组件为你的用户显示一个登录按钮。一旦用户通过认证,这个按钮就会变成一个注销按钮。该组件还提供了一个访问你将创建的Profile 页面的地方。
将Profile.jsx 加入到Pages 文件夹中。这个文件的代码如下。
import React, { useEffect } from "react";
import { Container } from "react-bootstrap";
import { useOktaAuth } from "@okta/okta-react";
import Header from "../Components/Header";
const Profile = () => {
const { authState, oktaAuth } = useOktaAuth();
useEffect(() => {
async function authenticate() {
if (!authState) return;
if (!authState.isAuthenticated) {
await oktaAuth.signInWithRedirect();
}
}
authenticate();
}, [authState, oktaAuth]);
if (!authState?.isAuthenticated) {
return (
<Container>
<p>Please wait while we sign you in</p>
</Container>
);
} else {
return (
<Container>
<Header authState={authState} oktaAuth={oktaAuth}></Header>
<h4>Your profile page</h4>
<p>Welcome to your profile page </p>
</Container>
);
}
};
export default Profile;
这个页面利用useOktaAuth 钩子来确定用户是否已经登录。如果用户没有登录,那么你将提示他们用Okta登录。否则,你将显示一个简短的个人资料页面。
最后,在Pages 文件夹中添加Home.jsx ,代码如下。
import React from "react";
import { Link, Redirect } from "wouter";
import Header from "../Components/Header";
import { Container, Row, Col, Card } from "react-bootstrap";
import { useOktaAuth } from "@okta/okta-react";
const Home = () => {
const { authState, oktaAuth } = useOktaAuth();
return authState?.isAuthenticated ? (
<Redirect to="/Profile" />
) : (
<Container>
<Header authState={authState} oktaAuth={oktaAuth}></Header>
<Row>
<Col sm={12} className="text-center">
<h3>React routing Demo</h3>
<h5>
A <a href="https://reactjs.org/">React</a> Demo using{" "}
<a href="https://github.com/molefrog/wouter">Wouter</a> Secured by{" "}
<a href="https://www.okta.com/">Okta</a>
</h5>
<p>
A tutorial written by{" "}
<a href="https://profile.fishbowlllc.com">Nik Fisher</a>
</p>
</Col>
</Row>
<br></br>
<Row>
<Col sm={12} className="text-center">
<Card style={{ width: "21.5em", margin: "0 auto" }}>
<Card.Header>Already have an Okta Account?</Card.Header>
<Card.Body>
<Link to="Profile">Login Here</Link>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
);
};
export default Home;
这个页面使用来自wouter的Redirect 组件,结合useOktaAuth 钩子,将认证的用户重定向到个人资料页面。该页面也作为一个登陆页面,提供一些关于你的应用程序的额外信息。
最后,你将需要用以下代码更新你的App.js 文件。
import React from "react";
import "./App.css";
import { Router, Route } from "wouter";
import { Security, LoginCallback } from "@okta/okta-react";
import { OktaAuth, toRelativeUrl } from "@okta/okta-auth-js";
import Home from "./Pages/Home";
import Profile from "./Pages/Profile";
import "bootstrap/dist/css/bootstrap.min.css";
const issuer = process.env.REACT_APP_OKTA_ISSUER;
const clientId = process.env.REACT_APP_OKTA_CLIENTID;
const redirect = process.env.REACT_APP_OKTA_APP_BASE_URL + "/callback";
class App extends React.Component {
constructor(props) {
super(props);
this.oktaAuth = new OktaAuth({
issuer: issuer,
clientId: clientId,
redirectUri: redirect,
});
this.restoreOriginalUri = async (_oktaAuth, originalUri) => {
window.location.replace(
toRelativeUrl(originalUri || "/", window.location.origin)
);
};
}
render() {
return (
<Router>
<Security
oktaAuth={this.oktaAuth}
restoreOriginalUri={this.restoreOriginalUri}
>
<Route path="/" component={Home} />
<Route path="/callback" component={LoginCallback} />
<Route path="/Profile" component={Profile} />
</Security>
</Router>
);
}
}
export default App;
6.0版的@okta/okta-react 库包括一些需要注意的变化,这取决于你最近使用的软件包的版本。
首先,你必须在<Security> 组件中提供restoreOriginalUri 属性。如果你以前使用的是4.x版本,你会注意到你需要将OktaAuth 对象注入到Security 组件中,而不是发行人、客户ID和其他信息。你可以在Okta的React GitHub页面上阅读更多关于这些变化的信息。
这里你也在导入bootstrap CSS。
最后,你通过在Okta的Security 组件中包裹wouterRouter 来设置路由。这将使你的路由能够访问Okta的API。
运行你的React应用程序
你的应用程序现在已经完成了。你可以使用npm start ,并导航到http://localhost:3000 来运行它。在那里,你点击登录按钮,这将显示Okta登录屏幕。一旦你登录成功,你就会被重定向到Profile 页面。
