给任意网页添加身份验证¶
在本指南中,您将使用 ExpressJS 搭建一个简单的网站服务器来托管 SPA 应用。我们还会用它来提供 HTML 页面及其所需的各种资源,如 JavaScript、CSS 等。您也可以在 GitHub 仓库中查看完整源代码。
准备工作¶
- 开始之前,请确保您的系统上已安装 Node.js。如果尚未安装,请从官方网站下载并安装。
- Authany 账号: 您需要一个 Authany 账号才能跟随本指南操作。如果还没有账号,可以在 Authany 网站上免费创建。
- 已注册的应用: 您需要在 Authany 中注册一个应用类型(单页应用)。请按照设置应用指南操作,并跳过安装 Authany Web SDK部分。您将通过 IIFE(立即调用函数表达式)打包文件从 Authany 的 CDN 获取 Authany Web SDK,并在 HTML 中直接引用该脚本。
创建基础 Web 服务器¶
首先在电脑上新建一个文件夹,用来存放应用的源代码(在示例中,我们将其命名为 authgear-spa-js-login)。然后运行以下命令初始化一个新的 NPM 项目:
接下来,安装两个必需的包:
同时安装 nodemon,这样在开发模式下代码发生变化时,服务器就能自动重启:
接下来,打开 package.json 文件,编辑 scripts 字段,加入 start 和 dev 命令,如下所示:
现在您可以用两种模式运行应用:生产模式和开发模式。
例如,npm run dev 会使用 nodemon 运行应用,并在您修改文件时监听变化。
创建 server.js¶
在项目根目录下创建一个新文件 server.js,并写入以下代码:
const express = require("express");
const { join } = require("path");
const app = express();
// Serve static assets from the /public folder
app.use(express.static(join(__dirname, "public")));
// Endpoint to serve the configuration file
app.get("/authgear_config.json", (req, res) => {
res.sendFile(join(__dirname, "authgear_config.json"));
});
// Serve the index page for all other requests
app.get("/*", (_, res) => {
res.sendFile(join(__dirname, "index.html"));
});
// Listen on port 3000
app.listen(3000, () => console.log("Application running on port 3000"));
创建基础 HTML 页面¶
在项目根目录下创建一个 index.html 文件,并添加以下内容:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Authgear SPA SDK Sample</title>
<link rel="stylesheet" type="text/css" href="/css/main.css" />
</head>
<body>
<h2>SPA Authentication Sample</h2>
<p>Welcome to our page!</p>
<button id="btn-login" disabled="true" onclick="login()">Log in</button>
<button id="btn-logout" disabled="true" onclick="logout()">Log out</button>
<script src="js/app.js"></script>
<script src="<https://unpkg.com/@authgear/web@2.2.0/dist/authgear-web.iife.js>"></script>
</body>
</html>
我们不使用像 Webpack 这样的打包工具,而是通过 IIFE(立即调用函数表达式)打包文件从 Authany 的 CDN 获取 Authany Web SDK。我们可以在 HTML 中直接引用该脚本:
您也可以将 Authany Web SDK 作为应用的依赖包安装,这在构建 React 或 React Native 应用时会很有用。了解如何安装该包。
创建 main.css 文件¶
在项目根目录下创建一个名为 public 的新文件夹,再在 public 文件夹内创建一个名为 css 的文件夹。在其中新建一个名为 main.css 的文件。它用来根据用户是否已通过身份验证,决定主页面上登录和登出按钮元素的显示或隐藏。
打开新建的 public/css/main.css 文件,添加以下 CSS:
创建好 HTML 文件并应用 CSS 样式后,运行 npm run dev 并访问 http://localhost:3000,看看页面现在的效果。

创建 app.js 文件¶
为了给页面添加一些交互,我们在 public 文件夹中新建一个名为 js 的目录,并在其中添加一个新文件 app.js。复制粘贴以下 JS 代码,它通过 fetchAuthConfig 函数从端点读取 authgear_config.json 文件中 Authany 应用的专属值(endpoint 和 clientId)。同时,它还会配置一个新的 Authany 客户端,并定义登录和登出逻辑:
let authgearClient = null;
const fetchAuthConfig = () => fetch("/authgear_config.json");
const configureClient = async () => {
const response = await fetchAuthConfig();
const config = await response.json();
authgearClient = window.authgear.default;
await authgearClient.configure({
endpoint: config.endpoint,
clientID: config.clientID,
sessionType: "refresh_token",
}).then(
() => {
console.log("Authgear client successfully configured!");
},
(err) => {
console.log("Failed to configure Authgear");
}
);
};
const login = async () => {
await authgearClient
.startAuthentication({
redirectURI: window.location.origin,
prompt: "login",
})
.then(
() => {
console.log("Logged in!");
},
(err) => {
console.log("Log in failed", err);
}
);
};
const logout = () => {
authgearClient
.logout({
redirectURI: window.location.origin,
})
.then(
() => {
console.log("Logged out successfully");
},
(err) => {
console.log("Failed to logout");
}
);
};
window.onload = async () => {
await configureClient();
updateUI();
const query = window.location.search;
if (query.includes("code=")) {
updateUI();
window.history.replaceState({}, document.title, "/");
}
}
const updateUI = async () => {
const isAuthenticated = authgearClient.sessionState === "AUTHENTICATED";
document.getElementById("btn-logout").disabled = !isAuthenticated;
document.getElementById("btn-login").disabled = isAuthenticated;
};
理解整体流程¶
让我们分解上一节中的 app.js 代码,了解 Authany 是如何实现身份验证的:
配置 Authany 客户端
fetchAuthConfig:首先,该函数会向我们在 server.js 中暴露的 /authgear_config.json 端点发起请求,从 authgear_config.json 文件中获取 Authany 应用的配置值。
configureClient:从 authgear_config.json 文件获取到 Authany 客户端的配置信息后,我们用这些设置来配置 Authany 客户端。它还会在控制台输出一条消息,说明配置是否成功。
登录流程
login:该函数由之前在 HTML 页面上定义的登录按钮调用。它通过调用 Authany 的 authgearClient.startAuthentication 函数来执行登录操作,将用户重定向到 Authany 登录页面。用户登录成功后,会被重定向回我们在 redirectURI 中设置的同一个页面。运行项目并点击登录按钮,您应该会跳转到为您的应用配置的 Authany 登录页面。

接下来创建一个新用户,或使用邮箱登录(我们在第一部分中指定了无密码邮箱登录方式)。当您尝试用邮箱登录时,系统会向您的邮箱发送一个魔法链接,用于确认登录操作。


身份验证成功后,您将被重定向回之前所在的页面。
登出流程
logout:该函数会将用户登出,并重定向回原始页面(http://localhost:3000)。它使用 Authany 的 logout 函数,并在控制台输出一条消息说明操作结果。
更新界面
window.onload:这是一个在页面加载时运行的函数。它会配置 Authany 客户端并更新界面。如果页面的 URL 中包含 “code=”,就说明用户已通过身份验证(code 是从 Authany 服务器接收到的查询参数),此时它会再次更新界面,并从 URL 中移除 “code=”。
评估身份验证状态
updateUI:该函数会根据用户是否已通过身份验证,更新登录和登出按钮的状态。在 Authany 中,您可以通过 sessionState 属性来检查用户是否已登录。如果用户已通过身份验证,我们会禁用登录按钮并启用登出按钮;如果用户未通过身份验证,则相反。