首页 / 资讯中心 / 文章详情

使用 Hanko Elements Web Components 构建现代化登录与注册体验:安装、集成、定制与国际化实战指南

使用 Hanko Elements Web Components 构建现代化登录与注册体验:安装、集成、定制与国际化实战指南 ★ FEATURED ARTICLE
后端认证鉴权前端【免费下载链接】hankoModern authentication, on your terms. Open source alternative to Auth0, Clerk, WorkOS, Stytch.项目地址https://gitcode.com/GitHub_Trending/ha/hanko点击查看免费下载Hanko Elements 是 Hanko 项目一个开源的现代身份认证方案提供的一套 Web Components 组件库帮助开发者以最少的代码为网站带来现代化的登录、注册与个人资料管理体验。它基于 frontend/frontend-sdk 与后端的 Hanko API 协同工作支持无密码认证Passkey/WebAuthn、邮箱验证码Passcode、密码、OTP 等多种认证方式。读完本文你将掌握从 npm/CDN 安装、register()注册、嵌入hanko-auth等组件、通过 frontend-sdk 管理会话到利用 CSS 变量与 Shadow Parts 深度定制 UI、配置多语言翻译的完整实战链路。核心特性一览Hanko Elements 的设计目标是开箱即用且高度可定制其核心能力包括用户认证提供安全、友好的用户认证处理方式可嵌入任意 Web 应用多种认证流程支持无密码认证Passkey与生物识别认证WebAuthn同时支持 Passcode、密码、OTP 等流程Web 组件库提供可定制的 Web Components通过标准 HTML 标签即可嵌入个人资料管理通过hanko-profile组件让用户查看并管理自己的资料信息邮箱、密码、Passkey 等事件处理为认证与会话相关事件提供监听机制方便自定义用户体验本地化与国际化支持多语言并提供翻译选项服务全球用户集成灵活性支持 CDN 或 npm 引入同时兼容 TypeScript 与非 TypeScript 环境视觉定制可通过 CSS 变量、Shadow Parts 等方式对齐品牌风格与应用整体设计。从仓库的 package.json 可以看到teamhanko/hanko-elements当前的入口为dist/elements.js内部依赖teamhanko/hanko-frontend-sdk、Preact 以及teamhanko/preact-custom-element用于将 Preact 组件注册为原生自定义元素。安装可通过 npm、yarn 或 pnpm 将 Hanko Elements 安装到项目中也可以直接通过 CDN 以模块方式引入见下文导入模块# npm npm install teamhanko/hanko-elements # yarn yarn add teamhanko/hanko-elements # pnpm pnpm install teamhanko/hanko-elements快速使用三步接入要集成 Hanko你需要从hanko-elements模块导入并调用register()函数随后即可在 HTML 中使用这些 Web Components。一个可用的页面至少需要放置hanko-auth元素让用户能够登录添加onSessionCreated事件处理器在认证流程完成后自定义后续行为例如跳转到其他页面。导入模块使用 webpack、Parcel 等模块打包器时在 TypeScript/JavaScript 文件中导入import { register } from teamhanko/hanko-elements;偏好 CDN 时使用script typemodule指向托管hanko-elements包的 CDN 地址script typemodule import { register } from https://cdn.jsdelivr.net/npm/teamhanko/hanko-elements/dist/elements.js; /script注册 Web Components调用register()函数将 Hanko API 的 URL 作为参数传入。该函数会把 Hanko 元素注册到浏览器的CustomElementRegistry中const { hanko } await register(https://hanko.yourdomain.com);也可以传入一组选项。从 src/Elements.tsx 的源码可以看到register()内部会用下列默认值合并你传入的选项并一次性注册hanko-auth、hanko-login、hanko-registration、hanko-profile、hanko-events五个组件const defaultOptions { shadow: true, // 设为 false 时不将 web component 挂载到 shadow DOM。 injectStyles: true, // 设为 false 时不注入任何默认样式。 enablePasskeys: true, // 设为 false 时不展示 passkey 相关内容。 hidePasskeyButtonOnLogin: false, // 隐藏登录页上用 passkey 登录的按钮。 translations: null, // 在此补充额外翻译。不传或传 null 时使用英文 // 传空对象 {} 则阻止元素展示任何翻译。 translationsLocation: /i18n, // 翻译文件所在 URL 或路径。 fallbackLanguage: en, // 翻译不可用时的回退语言。 storageKey: hanko, // 会话 token 存储的 cookie 名称同时也是本地存储 key 的前缀/名称。 cookieDomain: undefined, // SDK 设置的 cookie 生效域名为 undefined 时默认使用创建 cookie 的页面域名。 cookieSameSite: lax, // 指定 cookie 何时随跨站请求发送。 sessionCheckInterval: 30000, // 会话有效性检查间隔毫秒必须大于 30003 秒。 }; const { hanko } await register( https://hanko.yourdomain.com, defaultOptions );将https://hanko.yourdomain.com替换为你的 Hanko API 实际地址。除了文档列出的选项外源码中的RegisterOptions还暴露了sessionTokenLocation会话 token 的存储位置来自 frontend-sdk 的SessionTokenLocation供需要控制 token 存放方式的场景使用。嵌入 Web Components完成上述步骤后就可以在 HTMLbody中任意位置放置组件最小示例如下hanko-auth idauthComponent/hanko-auth script typemodule import { register } from https://cdn.jsdelivr.net/npm/teamhanko/hanko-elements/dist/elements.js; await register(https://hanko.yourdomain.com); const authComponent document.getElementById(authComponent); authComponent.addEventListener(onSessionCreated, () { // 跳转到其他页面 }); /script各组件说明如下。hanko-auth、hanko-login与hanko-registration这三个组件提供登录/注册的友好界面。区别在于hanko-auth可以在登录与注册界面之间切换hanko-login只负责登录hanko-registration只负责注册。Markup标记登录与注册的组合 UIhanko-auth/hanko-auth仅登录的 UIhanko-login/hanko-login仅注册的 UIhanko-registration/hanko-registrationAttributes属性prefilled-email预填邮箱输入框prefilled-username预填用户名输入框lang指定元素内容的语言参见翻译章节mode接受login或registration用于初始化hanko-auth组件的登录/注册流程nonce在应用了内容安全策略CSP时允许加载内联样式的 nonce 值。在源码层面mode对应AppProvider中的HankoAuthMode类型registration | loginAppProvider.tsx 会据此初始化对应的 Flow 名称login或registration。hanko-profile允许用户管理邮箱、密码与 Passkey 的组件。hanko-profile/hanko-profile属性lang语言、nonceCSP nonce。hanko-events一个不展示 UI、仅用于将事件处理器绑定到特定事件的组件。事件也可以通过hanko-auth、hanko-profile组件以相同方式订阅或通过 frontend-sdk 绑定见下一节。hanko-events idevents/hanko-events script document .getElementById(events) .addEventListener(onSessionCreated, console.log); // 还有更多事件可用参见 frontend-sdk 文档... /script从 AppProvider.tsx 的实现可以看到组件内部会把 frontend-sdk 的会话相关回调onSessionCreated、onSessionExpired、onUserLoggedOut、onUserDeleted、onBeforeStateChange、onAfterStateChange重新派发为对应的 DOM 自定义事件这正是hanko-events能够在页面层统一监听这些事件的原因。使用 Frontend-SDKregister()返回的hanko实例来自teamhanko/hanko-frontend-sdk可以完成会话验证、用户信息获取、登出等操作常用示例// 验证当前会话 const session await hanko.validateSession(); console.log(Session valid:, session.is_valid, Claims:, session.claims); // 获取会话 token const token hanko.getSessionToken(); console.log(Session token:, token); // 获取用户资料 const user await hanko.getCurrentUser(); console.log(User profile:, user.user_id, user.emails); // 登出用户 await hanko.logout(); console.log(User logged out); // 处理会话创建事件 hanko.onSessionCreated(({ claims }) { console.log(Session created with JWT claims:, claims); }); // 处理会话过期事件 hanko.onSessionExpired(() { console.log(Session expired, redirecting to login); }); // 处理用户登出事件 hanko.onUserLoggedOut(() { console.log(User logged out successfully); }); // 处理用户删除账号事件 hanko.onUserDeleted(() { console.log(User account deleted); });frontend-sdk 的完整实现位于 frontend/frontend-sdk/srcHanko.ts定义主类lib/client/下按职责拆分SessionClient、UserClient等客户端lib/events/则包含事件调度、会话通道与窗口活动管理等底层机制。一个值得参考的综合示例是仓库内的 src/example.html它在单个 HTML 文件中演示了hanko-auth、hanko-profile、hanko-events的协同使用——通过onSessionCreated在认证完成后从登录组件切换到资料组件、用onSessionExpired弹出会话过期对话框、用onUserLoggedOut恢复登录界面并配合语言下拉框实时切换lang属性还演示了hanko.validateSession()在页面初始化时判断会话有效性。UI 定制CSS 变量CSS 变量可用于按需定制hanko-auth与hanko-profile元素的样式全部变量及默认值如下hanko-auth, hanko-profile { /* 配色方案 */ --color: #333333; --color-shade-1: #8f9095; --color-shade-2: #e5e6ef; --brand-color: #506cf0; --brand-color-shade-1: #6b84fb; --brand-contrast-color: white; --background-color: white; --error-color: #e82020; --link-color: #506cf0; /* 字体样式 */ --font-weight: 400; --font-size: 16px; --font-family: sans-serif; /* 边框样式 */ --border-radius: 8px; --border-style: solid; --border-width: 1px; /* 条目样式 */ --item-height: 34px; --item-margin: 0.5rem 0; /* 容器样式 */ --container-padding: 30px; --container-max-width: 410px; /* 标题样式 */ --headline1-font-size: 24px; --headline1-font-weight: 600; --headline1-margin: 0 0 1rem; --headline2-font-size: 16px; --headline2-font-weight: 600; --headline2-margin: 1rem 0 0.5rem; /* 分隔线样式 */ --divider-padding: 0 42px; --divider-visibility: visible; /* 链接样式 */ --link-text-decoration: none; --link-text-decoration-hover: underline; /* 输入框样式 */ --input-min-width: 14em; /* 按钮样式 */ --button-min-width: max-content; }在 example.html 的样式中可以看到实际应用通过覆盖--color、--brand-color、--background-color、--border-radius等变量即可快速打造一套深色主题并通过#hankoAuth单独调整认证组件的--container-max-width与--container-padding实现不同组件之间的差异化布局。CSS Shadow Parts除了 CSS 变量还可以使用::part选择器定制各类元素。注意Shadow Parts 仅在组件挂载到 Shadow DOM 时生效这是默认行为可通过如下代码显式开启register(https://hanko.yourdomain.com, { shadow: true }); // 等价于 register(https://hanko.yourdomain.com);可用 Shadow Parts 列表container—— UI 容器headline1—— h1 标题headline2—— h2 标题paragraph—— 段落元素button—— 所有按钮primary-button—— 主按钮secondary-button—— 邮箱登录页上的次要按钮input—— 所有输入框text-input—— 非 passcode 的输入框passcode-input—— passcode 输入框link—— 页脚区域的链接error—— 错误消息容器error-text—— 错误消息文本divider—— 登录页的水平分隔线divider-text—— 分隔线文本divider-line——divider-text前后的线段form-item—— 表单项如输入框或按钮的容器使用示例示例 1强制hanko-auth内的输入框与按钮垂直堆叠::part(form-item)配合标签名定位style hanko-auth::part(form-item) { /* 让输入框和按钮上下排列 */ min-width: 100%; } /style hanko-auth/hanko-auth示例 2通过.hankoComponent::part(headline1)统一调整所有带hankoComponent类组件的标题style .hankoComponent::part(headline1) { /* 调整所有 hanko 组件的主标题 */ font-size: 1.3em; font-weight: 400; } /style hanko-auth classhankoComponent/hanko-auth hanko-profile classhankoComponent/hanko-profile示例 3借助 ID 选择器#hankoAuth::part(button):hover在悬停时为按钮添加阴影style #hankoAuth::part(button):hover { box-shadow: 3px 3px 2px #888; } /style hanko-auth idhankoAuth/hanko-authCSS Classes不推荐当组件未挂载到 Shadow DOM 时也可以提供自己的 CSS 规则register(https://hanko.yourdomain.com, { shadow: false });可以查看仓库内的 example.css 了解可用的 CSS 规则。如果只想修改特定属性覆盖预定义的即可例如修改背景色.hanko_container { background-color: blue !important; }也可以完全禁止注入样式register(https://hanko.yourdomain.com, { shadow: false, injectStyles: false, });这样就不需要覆盖属性而是提供全部 CSS 规则.hanko_container { background-color: blue; } /* 更多 css 规则... */如果偏好这种方式建议以 example.css 为起点按需修改后引入页面。需要了解的是官方提供 CSS Classes 与 light DOM 支持仅仅是因为 Safari 存在一个 bug——组件挂载在 Shadow DOM 时输入元素的自动补全会失效。正常情况下更推荐将组件挂载到 Shadow DOM并在 CSS 变量不够用时使用 CSS Parts 进行 UI 定制。翻译与国际化默认行为hanko-elements默认自带英文翻译lang属性可以省略register(https://hanko.yourdomain.com);hanko-auth/hanko-auth安装更多翻译当前提供的语言如下bn—— 孟加拉语de—— 德语en—— 英语fr—— 法语it—— 意大利语nl—— 荷兰语ptBR—— 巴西葡萄牙语zh—— 简体中文可以逐个导入// 若使用 CDN请将下列路径替换为 // https://cdn.jsdelivr.net/npm/teamhanko/hanko-elements/dist/i18n/{en|de|all|...}.js import { bn } from teamhanko/hanko-elements/i18n/bn; import { de } from teamhanko/hanko-elements/i18n/de; import { en } from teamhanko/hanko-elements/i18n/en; import { fr } from teamhanko/hanko-elements/i18n/fr; import { it } from teamhanko/hanko-elements/i18n/it; import { nl } from teamhanko/hanko-elements/i18n/nl; import { ptBR } from teamhanko/hanko-elements/i18n/pt-BR; import { zh } from teamhanko/hanko-elements/i18n/zh;或者一次性导入全部翻译import { all } from teamhanko/hanko-elements/i18n/all;导入后通过register()提供register(https://hanko.yourdomain.com, { translations: { bn, de, en, fr, it, nl, ptBR, zh } }); // 或 register(https://hanko.yourdomain.com, { translations: all });随后即可用lang属性指定元素语言hanko-auth langde/hanko-auth仓库的 src/i18n 目录保存了各语言文件en.ts、de.ts、zh.ts、pt-BR.ts等all.ts汇总导出全部语言。从 package.json 的exports/typesVersions配置可以看到teamhanko/hanko-elements/i18n/*子路径在 npm 包中是公开导出、可被单独导入的。修改现有翻译可以像下面这样直接修改导入的翻译对象import { en } from teamhanko/hanko-elements/i18n/en; en.errors.somethingWentWrong Aww, snap!; register(https://hanko.yourdomain.com, { translations: { en } });新增翻译如果要创建新语言传入一个实现或部分实现Translation接口的对象import { all } from teamhanko/hanko-elements/i18n/all; import { Translation } from teamhanko/hanko-elements; // TypeScript 环境 const myLang: Translation {...} register(https://hanko.yourdomain.com, {translations: {...all, myLang}});hanko-auth langmyLang/hanko-authTranslation接口的结构定义在 src/i18n/translations.ts涵盖headlines、texts、labels、errors、flowErrors五个分组其中flowErrors与后端 Flow API 的错误码一一对应如flow_expired_error、passcode_invalid、rate_limit_exceeded等实现新语言时可以此为准。使用外部文件对于通过元素lang属性或fallbackLanguage指定、但未包含在translations选项对象中的语言组件会从translationsLocation选项指定的位置拉取 JSON 文件。例如下面示例中由于传入了空对象即使默认的 en 也不可用组件会拉取名为/i18n/en.json的文件register(https://hanko.yourdomain.com, { translations: {}, // 空对象连默认的 en 翻译也不可用 translationsLocation: /i18n, // 存放语言文件的公开目录例如 en.json });!-- 将拉取 /i18n/en.json -- hanko-auth langen/hanko-auth回退语言fallbackLanguage选项用于指定回退语言当某语言的翻译缺失或不完整时自动从回退语言补取缺失的字符串。若回退语言在translations选项中也不可用组件会尝试从外部文件拉取import { en } from teamhanko/hanko-elements/i18n/en; import { Translation } from teamhanko/hanko-elements; const symbols: PartialTranslation { labels: { continue: ➔ }, }; register(https://hanko.yourdomain.com, { fallbackLanguage: en, translations: { en, symbols }, });!-- 界面整体显示英文但 continue 按钮文案为 ➔ -- hanko-auth langsymbols/hanko-auth这一机制在源码中体现为 AppProvider.tsx 通过TranslateProvider组合translations、fallbackLang与root即translationsLocation三个参数交给denysvuika/preact-translate运行时解析。对 Hanko 外发邮件语言的影响使用 Hanko Elements 时组件上lang属性的语言也会传递给 Hanko API用于决定外发邮件的语言。如果停用了 Hanko 的邮件投递、并为email.send事件配置了 Webhook那么lang属性的值会体现在 Webhook 请求所携带 token 的 JWT payload 的languageclaim 中。官方示例与框架集成仓库内提供了可直接运行的参考实现演示在纯 JavaScript 与主流前端框架中的集成方式frontend/elements/src/example.html单个 HTML 文件实现了本页提及的大多数功能关键细节以注释说明可在任意 HTTP 服务器含本地上托管运行frontend/examples/README.mdTodo 示例应用展示 Hanko 在 Angular、React、Vue、Next.js 等框架中的集成并讲解后端通信与 JWT 校验的管理方式。包导出内容teamhanko/hanko-elements导出以下函数与接口并额外导出 frontend-sdk 的全部声明src/index.ts 通过export *实现函数register—— 将 Web Components 注册到浏览器自定义元素注册表。接口RegisterOptions——register()函数的选项RegisterResult——register()函数的返回值包含hanko实例Translation—— 可通过RegisterOptions提供的翻译结构HankoAuthElementProps——hanko-auth元素属性HankoProfileElementProps——hanko-profile元素属性HankoEventsElementProps——hanko-events元素属性。上述属性接口在 Elements.tsx 中声明并且该文件同时为 JSX 命名空间补充了hanko-auth、hanko-login、hanko-registration、hanko-profile、hanko-events五个内建元素类型支持在 React 19 及 TypeScript 环境中获得类型提示。浏览器支持SafariFirefoxOpera基于 Chromium 的浏览器Chrome、Edge、Brave 等已知问题可定制 UI在 Chrome 中::part选择器与某些伪类组合时存在缺陷例如:disabled当前无法正常工作。许可证elements项目以 MIT 许可证发布详见 frontend/elements/LICENSE。结合本文内容一个典型的落地路径是先通过 npm/CDN 安装并调用register()接入hanko-auth配合onSessionCreated事件与 frontend-sdk 的validateSession()完成基础认证闭环随后利用 CSS 变量与 Shadow Parts 对齐品牌视觉最后通过 i18n 模块、lang属性与fallbackLanguage完成国际化。如果需要在认证成功/失败/过期等关键时刻介入业务逻辑hanko-events与 frontend-sdk 的事件订阅是推荐的统一入口。赞分享后端认证鉴权前端【免费下载链接】hankoModern authentication, on your terms. Open source alternative to Auth0, Clerk, WorkOS, Stytch.项目地址https://gitcode.com/GitHub_Trending/ha/hanko点击查看免费下载相关推荐从入门到精通Kissui.scrollanim事件系统全解析从入门到精通Kissui.scrollanim事件系统全解析 Kissui.scrollanim是一个轻量级的CSS3滚动动画库它结合了CSS3和JavaS如何快速搭建ONIE开发环境Docker镜像构建完整指南如何快速搭建ONIE开发环境Docker镜像构建完整指南 ONIEOpen Network Install Environment是一款开源网络安装环境工嵌入式操作系统固件Formily 登录注册实战指南用 formily/antd 构建账密登录、手机验证码登录与完整注册表单Formily 登录注册实战指南用 formily/antd 构建账密登录、手机验证码登录与完整注册表单 Formily 是一套跨端、高性能的表单解决方案前端UI组件上一篇5分钟掌握JDspyder京东自动化抢购脚本的终极使用指南下一篇Open Mercato销售模块实战指南从报价、订单到发货的完整流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站