手把手教你使用 Fastify 框架搭建统一认证中心
在互联网和移动互联网时代,统一认证中心(Single Sign-On,简称 SSO)成为了重要的认证和授权方式。它通过一次登录即可实现所有应用的登录和授权,提高了用户的使用体验和安全性。
本文将手把手教你使用 Fastify 框架搭建统一认证中心,让你在前端类的应用中也能轻松实现 SSO 认证,方便用户快速登录并实现授权。
快速概述
Fastify 是 Node.js 的一个轻量级、高效的 Web 框架,目前广泛应用于 RESTful API 和微服务的开发。在本文中,我们将利用 Fastify 框架搭建一个简单的统一认证中心,实现两个应用的 SSO 认证和授权。
- 统一认证中心:提供登录和授权的功能。
- 应用 A:需要进行 SSO 认证和授权。
- 应用 B:需要进行 SSO 认证和授权。
基础介绍
在开始之前,你需要了解以下内容:
- 基础的 Node.js 知识和 JavaScript 语言。
- 熟悉 HTTP 协议和 RESTful API 的基础概念。
- 熟悉 JSON Web Token(JWT) 的基础概念。
项目准备
首先,我们需要创建一个新的项目目录,使用 npm 初始化:
mkdir sso-demo cd sso-demo npm init -y
项目结构
我们需要创建以下目录,来放置项目的代码和配置文件。
-- -------------------- ---- ------- -------- --- --------- --- ------------ --- ------ --- ---- - --- -------- - --- ------------ - --- ------- - --- ---------- - --- ---- - --- -------- - --- ------------ - --- ------- - --- ----------
- config.js:存放配置项,例如 JWT 密钥和端口号等。
- app.js:主文件,用于启动认证中心服务。
- appA、appB:两个应用的目录,每个目录下包含应用自身的代码和配置。
- public:存放应用的前端代码和页面文件。
初始化项目
我们需要安装以下依赖:
- fastify:用于搭建认证中心和应用。
- fastify-jwt:用于 JWT 的生成和验证。
- fastify-cookie:用于存储和获取用于 SSO 的 Cookie。
- fastify-cors:用于跨域请求。
- fastify-auth:用于验证 token 的有效性。
npm install fastify fastify-jwt fastify-cookie fastify-cors fastify-auth --save
认证中心
认证中心是一个 Web 应用程序,用于提供登录和授权的功能。在本示例中,我们将创建以下路由:
- /login:用于用户登录,生成 JWT token 并使用 Cookie 存储。
- /logout:用于用户注销,删除 Cookie 中的 token。
创建认证中心
我们创建一个新的文件 app.js,作为认证中心的主要入口,它将通过 Fastify 启动 HTTP 服务器,并定义路由和中间件。
-- -------------------- ---- ------- ----- ------- - -------------------- ------- ---- -- ----- - ----------- - - ------------------ ----- - ----- --------- - - ------------------- ----- ------ - ------------------- -- ---- -- ----------------------------------------- - ------- ---- -------- ------- ------ ------- ---------- --------------- ---------------- ----------------- -- -- --- ----- ----------------------------------------- ----- ---- ----- -- - --- - ----- ----- - ----------------- -------------------- ----- -------- -- - -- ----- ----- --- -------- - ------- -- ------ - ----- --- - ---------------------- ------ -------------- -- - -- -- ---- ------------------------ -- ----- ----- ----- - ----- -- -- - --- - ----- -------------------- ------------------------ --------- -- ---- --------- - ----- ----- - ---------------------- --------------- - - -------
其中,我们使用了 fastify-cors、fastify-auth 插件,用于跨域请求和 JWT 鉴权。
在创建认证中心前,我们需要定义一些辅助方法,用于生成 JWT token 和验证 token。
生成 JWT token
我们创建一个 utils.js 文件,用于将一些工具函数进行封装,方便我们的调用。
-- -------------------- ---- ------- ----- ---------- - ---------------------- ----- - --------- - - ------------------- ----- ----------- - --------- -- - ------ ------------------------ ---------- - -------------- - - ------------ -
我们使用 fastify-jwt 生成 JWT token。
验证 JWT token
在使用 JWT token 时,我们需要对 token 进行解析验证,可使用下列方法:
-- -------------------- ---- ------- -- ------ -------- -- -- ----- ----- ----- - ----------------- -- -- --- ----- ------------------------- ----- -------- -- - -- ----- - ------ ----- - -------------------- -- - --------- ----- - ------ ---- --
定义路由
接着,我们定义好认证中心的路由。我们使用 fastify-cors 支持跨域请求,fastify-cookie 存储 token。
登录成功将生成 token 并存储在 Cookie 中,注销成功则删除 Cookie。
-- -------------------- ---- ------- ----- - ----------- - - ------------------ -------------- - ----- -------- --------- -------- - ---------------------- ----- ----- ------ -- - ----- - --------- -------- - - -------- -- ---------- -- ---------- - ------------------------ ------ --------- -- -------- --------- -- ------ - -- ---------- -- --------- --- ------- -- -------- --- --------- - ------------------------ ------ -------------- -- ------ - -- -- --- ----- ----- ----- - ----------------------- -- - ----- --- ------ - ------------------------ ------ - ----- ---- --------- ----- -------- --- --------------- - -- - -- - -- - ----- -- ------------ -------- ---- -- -- ----------------------- ----- ----- ------ -- - -- -- ----- -------------------------- - ----- --- -- ------------ -------- ---- -- -- -
验证用户身份
在我们的应用中,我们需要通过 SSO 进行授权,因此需要对 token 进行解析验证用户身份。
我们在上文中,已经编写过一个 fastify-auth 的插件支持 JWT 验证中间件,并将其在 app.js 中引入,代码如下:
-- -------------------- ---- ------- -- --- ----- ----------------------------------------- ----- ---- ----- -- - --- - ----- ----- - ----------------- -------------------- ----- -------- -- - -- ----- ----- --- -------- - ------- -- ------ - ----- --- - ---------------------- ------ -------------- -- - --
应用 A
应用 A 是一个 Web 应用程序,它需要进行 SSO 认证和授权。
在 appA 目录下,我们新建一个 index.js 文件,用于启动 HTTP 服务器,并引入 fastify、fastify-cookie 和 fastify-auth 插件,代码如下:
-- -------------------- ---- ------- ----- ------- - -------------------- ------- ---- -- -- -- ------- ------------------------------------------- -- -- -------------- -- ----------------------------------------- -- -- ------------ -- ----- - ----- ----------------- --------- - - -------------------- -- ------ ----- ------ - ------------------- -- ---- -- ---- ----------------------------------------- - ------- ---- -------- ------- ------ ------- ---------- --------------- ---------------- ----------------- -- -- ----- ---------------------- --------- -- - ----------------------------- ----- ----- ---- -- - ----- ------- - ----- --------------- ----------- - ------- -- -- -- ---- ------------------------ -- ----- ----- ----- - ----- -- -- - --- - ----- -------------------- ------------------------ --------- -- ---- --------- - ----- ----- - ---------------------- --------------- - - -------
在 appA 下创建了 routes.js 文件,用于定义应用 A 的路由,其中包含:
- /ping:测试应用 A 是否正常工作。
- /login:跳转到认证中心进行登录认证。
- /dashboard:当验证中心认证成功后跳转到的页面。
-- -------------------- ---- ------- -------------- - ----- -------- --------- -------- - -- ------ -------------------- ----- ----- ---- -- - ------------------ ---------- ---------- -- -- --- --------------------- ----- ----- ---- -- - ------------------------ -- -- ------ -- ----- ----------------------------------------- -- ----------- -- -- -------- ------------------------- ----- ----- ---- -- - ------------------- ------ -- -
应用 B
应用 B 是一个 Web 应用程序,它需要进行 SSO 认证和授权。
在 appB 目录下,我们新建一个 index.js 文件,用于启动 HTTP 服务器,并引入 fastify、fastify-cookie 和 fastify-auth 插件,代码如下:
-- -------------------- ---- ------- ----- ------- - -------------------- ------- ---- -- -- -- ------- ------------------------------------------- -- -- -------------- -- ----------------------------------------- -- -- ------------ -- ----- - ----- ----------------- --------- - - -------------------- -- ------ ----- ------ - ------------------- -- ---- -- ---- ----------------------------------------- - ------- ---- -------- ------- ------ ------- ---------- --------------- ---------------- ----------------- -- -- ----- ---------------------- --------- -- - ----------------------------- ----- ----- ---- -- - ----- ------- - ----- --------------- ----------- - ------- -- -- -- ---- ------------------------ -- ----- ----- ----- - ----- -- -- - --- - ----- -------------------- ------------------------ --------- -- ---- --------- - ----- ----- - ---------------------- --------------- - - -------
在 appB 下创建了 routes.js 文件,用于定义应用 B 的路由,其中包含:
- /ping:测试应用 B 是否正常工作。
- /login:跳转到认证中心进行登录认证。
- /dashboard:当验证中心认证成功后跳转到的页面。
-- -------------------- ---- ------- -------------- - ----- -------- --------- -------- - -- ------ -------------------- ----- ----- ---- -- - ------------------ ---------- ---------- -- -- --- --------------------- ----- ----- ---- -- - ------------------------ -- -- ------ -- ----- ----------------------------------------- -- ----------- -- -- -------- ------------------------- ----- ----- ---- -- - ------------------- ------ -- -
完整示例代码
下面是完整代码,你可以在代码中更改端口号,配置项等。
config.js
module.exports = { port: 3000, jwtSecret: 'sso-secret-123', remoteAuthServer: 'http://localhost:4000', }
app.js
-- -------------------- ---- ------- ----- ------- - -------------------- ------- ---- -- ----- - ----------- - - ------------------ ----- - ----- --------- - - ------------------- ----- ------ - ------------------- -- ---- -- ----------------------------------------- - ------- ---- -------- ------- ------ ------- ---------- --------------- ---------------- ----------------- -- -- --- ----- ----------------------------------------- ----- ---- ----- -- - --- - ----- ----- - ----------------- -------------------- ----- -------- -- - -- ----- ----- --- -------- - ------- -- ------ - ----- --- - ---------------------- ------ -------------- -- - -- -- ---- ------------------------ -- ----- ----- ----- - ----- -- -- - --- - ----- -------------------- ------------------------ --------- -- ---- --------- - ----- ----- - ---------------------- --------------- - - -------
utils.js
-- -------------------- ---- ------- ----- ---------- - ---------------------- ----- - --------- - - ------------------- ----- ----------- - --------- -- - ------ ------------------------ ---------- - -------------- - - ------------ -
appA/index.js
-- -------------------- ---- ------- ----- ------- - -------------------- ------- ---- -- ------------------------------------------- ----------------------------------------- ----- - ----- ----------------- --------- - - -------------------- ----- ------ - ------------------- -- ---- ------ ----------------------------------------- - ------- ---- -------- ------- ------ ------- ---------- --------------- ---------------- ----------------- -- -- ----- ---------------------- --------- -- - ----------------------------- ----- ----- ---- -- - ----- ------- - ----- --------------- ----------- - ------- -- -- -- ---- ------------------------ -- ----- ----- ----- - ----- -- -- - --- - ----- -------------------- ------------------------ --------- -- ---- --------- - ----- ----- - ---------------------- --------------- - - -------
appA/routes.js
-- -------------------- ---- ------- -------------- - ----- -------- --------- -------- - -- ------ -------------------- ----- ----- ---- -- - ------------------ ---------- ---------- -- -- --- --------------------- ----- ----- ---- -- - ------------------------ -- -- ------ -- ----- ----------------------------------------- -- ----------- -- -- -------- ------------------------- ----- ----- ---- -- - ------------------- ------ -- -
appB/index.js
-- -------------------- ---- ------- ----- ------- - -------------------- ------- ---- -- ------------------------------------------- ----------------------------------------- ----- - ----- ----------------- --------- - - -------------------- ----- ------ - ------------------- -- ---- ------ ----------------------------------------- - ------- ---- -------- ------- ------ ------- ---------- --------------- ---------------- ----------------- -- -- ----- ---------------------- --------- -- - ----------------------------- ----- ----- ---- -- - ----- ------- - ----- --------------- ----------- - ------- -- -- -- ---- ------------------------ -- ----- ----- ----- - ----- -- -- - --- - ----- -------------------- ------------------------ --------- -- ---- --------- - ----- ----- - ---------------------- --------------- - - -------
appB/routes.js
-- -------------------- ---- ------- -------------- - ----- -------- --------- -------- - -- ------ -------------------- ----- ----- ---- -- - ------------------ ---------- ---------- -- -- --- --------------------- ----- ----- ---- -- - ------------------------ ----------------------------------------- -- -- -------- ------------------------- ----- ----- ---- -- - ------------------- ------ -- -
使用说明
我们已经创建好了一个统一认证中心和两个应用 A、B,依次启动三个服务:认证中心服务、应用 A 服务、应用 B 服务:
node app.js node appA/index.js node appB/index.js
访问地址
- 认证中心: http://localhost:3000
- 应用 A:http://localhost:3001
- 应用 B:http://localhost:3002
说明
首先,访问应用 A,跳转到认证中心进行登录;登录成功后,可访问 Dashboard Page 页面。
在访问应用 B 时,也跳转到认证中心进行登录,成功后可访问 Dashboard Page 页面。
结论
本文已对使用 Fastify 框架搭建统一认证中心进行了详细的解释和演示,在你的实际应用中时,你可以根据自身情况进行相应部署操作。希望这篇文章对大家能有所帮助,欢迎交流和指正。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/674c5e1ea336082f2540ccd5