diff --git a/SDK_MODIFICATIONS.md b/SDK_MODIFICATIONS.md new file mode 100644 index 0000000..d73c297 --- /dev/null +++ b/SDK_MODIFICATIONS.md @@ -0,0 +1,127 @@ +# FIDO2 UI SDK 修改说明 + +## 修改概述 + +根据需求,对UI SDK进行了以下修改: + +1. **增加用户ID参数**:renderDeviceManager函数现在需要userId参数 +2. **删除登录功能**:移除了登录相关的UI和事件处理 +3. **简化设备管理**:设备操作现在直接使用传入的用户ID + +## 主要修改 + +### 1. renderDeviceManager函数 + +**修改前:** +```javascript +Fido2UIManager.renderDeviceManager({ + container: '#device-container', + mode: 'modal', + serverUrl: SERVER_URL +}); +``` + +**修改后:** +```javascript +Fido2UIManager.renderDeviceManager({ + userId: 'user@example.com', // 新增必需参数 + container: '#device-container', + mode: 'modal', + serverUrl: SERVER_URL +}); +``` + +### 2. DeviceManager修改 + +- `addDevice()`: 使用`this.config.userId`代替从sessionStorage获取用户ID +- `deleteDevice()`: 使用`this.config.userId`代替从sessionStorage获取用户ID +- `checkSession()`: 简化为始终返回true(假设用户已登录) +- `getUserId()`: 返回`this.config.userId` + +### 3. 删除的功能 + +- 移除了登录按钮的UI渲染 +- 移除了login事件处理器 +- 移除了session检查逻辑 +- 移除了getSessionData方法 + +### 4. 错误处理 + +如果未提供userId参数,renderDeviceManager会抛出错误: +``` +'userId is required for device management operations' +``` + +## 使用示例 + +### 模式1:模态框模式 + +```javascript +Fido2UIManager.renderDeviceManager({ + userId: 'user@example.com', + container: '#device-container', + mode: 'modal', + serverUrl: 'https://your-server.com', + language: 'en-US', + callbacks: { + onInit: function(manager) { + console.log('Device manager initialized'); + }, + onDeviceAdded: function(device) { + console.log('Device added:', device); + }, + onDeviceDeleted: function(deviceId) { + console.log('Device deleted:', deviceId); + }, + onDeviceListLoaded: function(devices) { + console.log('Devices loaded:', devices); + }, + onError: function(error) { + console.error('Error:', error); + }, + onClose: function() { + console.log('Device manager closed'); + } + } +}); +``` + +### 模式2:独立页面模式 + +```javascript +Fido2UIManager.renderDeviceManager({ + userId: 'user@example.com', + mode: 'standalone', + serverUrl: 'https://your-server.com', + language: 'zh-CN', + theme: { + primaryColor: '#007bff', + backgroundColor: '#f8f9fa' + }, + features: { + showAddButton: true, + showDeleteButton: true, + showUserInfo: true, + showSessionStatus: true + } +}); +``` + +## 注意事项 + +1. **userId参数是必需的**:不提供userId会导致错误 +2. **假设用户已登录**:不再进行登录状态检查 +3. **向后兼容**:此修改可能会影响现有集成,需要更新调用代码 +4. **删除的API**:renderLogin函数仍然存在,但如果不再需要可以移除 + +## 测试 + +可以使用test-device-manager.html文件测试修改后的功能。 + +## 依赖关系 + +确保在调用renderDeviceManager之前已经加载了: +- jQuery +- Bootstrap JS +- dfido2-lib.js +- fido2-ui-sdk.js diff --git a/app-callback.html b/app-callback.html new file mode 100644 index 0000000..51dea72 --- /dev/null +++ b/app-callback.html @@ -0,0 +1,35 @@ + + + + + + amiPro App Callback + + + + +
+

SSO Complete

+

You can return to the app.

+

Session:

+

User:

+

rpId:

+
+ + diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..232cd78 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,641 @@ +# FIDO2 UI SDK - API 文档 + +## 目录 + +- [全局对象](#全局对象) +- [配置选项](#配置选项) +- [API 方法](#api-方法) +- [事件系统](#事件系统) +- [国际化](#国际化) +- [主题定制](#主题定制) + +--- + +## 全局对象 + +### Fido2UIManager + +全局 FIDO2 UI 管理对象。 + +```javascript +window.Fido2UIManager +``` + +--- + +## 配置选项 + +### config + +配置对象,用于初始化设备管理器。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| serverUrl | String | 'https://fido2.amipro.me' | FIDO2 服务器地址 | +| mode | String | 'modal' | 渲染模式:'modal' \| 'standalone' | +| container | String \| Element | null | 容器选择器或 DOM 元素(modal 模式必需) | +| theme | Object | 见下方 | 主题配置 | +| language | String | 'zh-CN' | 语言:'en-US' \| 'zh-CN' \| 'ja' | +| customI18n | Object | {} | 自定义翻译 | +| features | Object | 见下方 | 功能开关 | +| callbacks | Object | {} | 事件回调 | +| rpId | String \| null | null | Relying Party ID | +| autoRefresh | Boolean | true | 是否自动刷新设备列表 | +| refreshInterval | Number | 5000 | 刷新间隔(毫秒) | + +### config.theme + +主题配置对象。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| logo | String \| null | null | Logo 图片 URL | +| primaryColor | String | '#696cff' | 主色调(十六进制颜色值) | +| backgroundColor | String | '#ffffff' | 背景色 | +| textColor | String | '#333333' | 文字颜色 | +| borderRadius | String | '8px' | 圆角大小 | + +### config.features + +功能开关对象。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| showAddButton | Boolean | true | 是否显示添加按钮 | +| showDeleteButton | Boolean | true | 是否显示删除按钮 | +| showUserInfo | Boolean | true | 是否显示用户信息 | +| showSessionStatus | Boolean | true | 是否显示会话状态 | + +### config.callbacks + +事件回调对象。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| onInit | Function | null | 初始化完成回调 | +| onDeviceAdded | Function | null | 设备添加成功回调 | +| onDeviceDeleted | Function | null | 设备删除成功回调 | +| onDeviceListLoaded | Function | null | 设备列表加载完成回调 | +| onError | Function | null | 错误发生回调 | +| onClose | Function | null | 窗口关闭回调(仅 modal 模式) | + +--- + +## API 方法 + +### renderDeviceManager(config) + +渲染设备管理器。 + +**语法:** + +```javascript +Fido2UIManager.renderDeviceManager(config) +``` + +**参数:** + +- `config` (Object) - 配置对象,详见[配置选项](#配置选项) + +**返回值:** + +- (Object) - 设备管理器实例 + +**示例:** + +```javascript +const manager = Fido2UIManager.renderDeviceManager({ + container: '#device-container', + mode: 'modal', + serverUrl: 'https://fido2.amipro.me' +}); +``` + +--- + +### close() + +关闭模态框(仅 modal 模式有效)。 + +**语法:** + +```javascript +Fido2UIManager.close() +``` + +**示例:** + +```javascript +Fido2UIManager.close(); +``` + +--- + +### refresh() + +刷新设备列表和会话状态。 + +**语法:** + +```javascript +Fido2UIManager.refresh() +``` + +**示例:** + +```javascript +Fido2UIManager.refresh(); +``` + +--- + +### destroy() + +销毁设备管理器实例,清理资源。 + +**语法:** + +```javascript +Fido2UIManager.destroy() +``` + +**示例:** + +```javascript +Fido2UIManager.destroy(); +``` + +--- + +## 事件系统 + +### 事件列表 + +| 事件名称 | 触发时机 | 回调参数 | +|---------|---------|---------| +| `init` | 初始化完成 | (manager: Object) | +| `deviceAdded` | 设备添加成功 | (device: Object) | +| `deviceDeleted` | 设备删除成功 | (deviceId: String) | +| `deviceListLoaded` | 设备列表加载完成 | (devices: Array) | +| `sessionStatusChanged` | 会话状态改变 | (isValid: Boolean) | +| `error` | 发生错误 | (error: Error) | +| `close` | 窗口关闭 | 无 | + +### 事件参数详解 + +#### init + +初始化完成时触发。 + +**参数:** + +- `manager` (Object) - 设备管理器实例 + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onInit: function(manager) { + console.log('设备管理器已初始化', manager); + } + } +}); +``` + +#### deviceAdded + +设备添加成功时触发。 + +**参数:** + +- `device` (Object) - 添加的设备信息 + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onDeviceAdded: function(device) { + console.log('设备添加成功', device); + // 刷新用户界面 + refreshUserInterface(); + } + } +}); +``` + +#### deviceDeleted + +设备删除成功时触发。 + +**参数:** + +- `deviceId` (String) - 被删除设备的 ID + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onDeviceDeleted: function(deviceId) { + console.log('设备删除成功', deviceId); + // 显示成功提示 + showNotification('设备删除成功'); + } + } +}); +``` + +#### deviceListLoaded + +设备列表加载完成时触发。 + +**参数:** + +- `devices` (Array) - 设备列表 + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onDeviceListLoaded: function(devices) { + console.log('设备列表加载完成,共', devices.length, '个设备'); + } + } +}); +``` + +#### sessionStatusChanged + +会话状态改变时触发。 + +**参数:** + +- `isValid` (Boolean) - 会话是否有效 + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onSessionStatusChanged: function(isValid) { + if (isValid) { + console.log('会话有效'); + } else { + console.log('会话无效,请重新登录'); + } + } + } +}); +``` + +#### error + +发生错误时触发。 + +**参数:** + +- `error` (Error) - 错误对象 + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onError: function(error) { + console.error('发生错误:', error.message); + // 显示错误提示 + showErrorNotification(error.message); + } + } +}); +``` + +#### close + +模态框关闭时触发(仅 modal 模式)。 + +**参数:** + +- 无 + +**示例:** + +```javascript +Fido2UIManager.renderDeviceManager({ + callbacks: { + onClose: function() { + console.log('模态框已关闭'); + } + } +}); +``` + +--- + +## 国际化 + +### 支持的语言 + +- `en-US` - 英文 +- `zh-CN` - 简体中文 +- `ja` - 日文 + +### 设置语言 + +通过 `language` 参数设置语言: + +```javascript +Fido2UIManager.renderDeviceManager({ + language: 'zh-CN' +}); +``` + +### 默认翻译键 + +| 键 | 英文 | 中文 | 日文 | +|----|------|------|------| +| `my_devices` | My devices | 我的设备 | マイデバイス | +| `btn_add` | Add device | 添加设备 | デバイスを追加 | +| `title_device` | Device | 设备 | デバイス | +| `title_time` | Registered time | 添加时间 | 登録時間 | +| `title_act` | Actions | 操作 | 操作 | +| `title_del` | Delete | 删除 | 削除 | +| `title_logout` | Log out | 登出 | ログアウト | +| `title_empty_list` | No devices, please add. | 无设备,请添加。 | デバイスがなし、追加してください。 | +| `msg_register_ok` | Device registered successfully | 添加设备成功 | デバイス登録完了 | +| `msg_deldev_ok` | Device deleted successfully | 设备删除成功 | デバイスを削除しました | +| `msg_confirm_deldev` | Do you want to delete this device? | 确认删除此设备吗? | デバイスを削除しますか? | +| `msg_session_status_ok` | FIDO2 session is valid | FIDO2会话正常 | FIDO2セッションは正常です | +| `msg_session_status_fail` | FIDO2 session is invalid | FIDO2会话无效 | FIDO2セッションは無効です | +| `btn_close` | Close | 关闭 | 閉じる | +| `title_welcome` | Welcome | 欢迎 | ようこそ | + +### 自定义翻译 + +通过 `customI18n` 参数自定义翻译: + +```javascript +Fido2UIManager.renderDeviceManager({ + language: 'zh-CN', + customI18n: { + 'my_devices': { + 'zh-CN': '我的 FIDO2 设备' + }, + 'btn_add': { + 'zh-CN': '添加新设备' + } + } +}); +``` + +--- + +## 主题定制 + +### 主题配置参数 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| logo | String \| null | null | Logo 图片 URL | +| primaryColor | String | '#696cff' | 主色调 | +| backgroundColor | String | '#ffffff' | 背景色 | +| textColor | String | '#333333' | 文字颜色 | +| borderRadius | String | '8px' | 圆角大小 | + +### 基础主题定制 + +```javascript +Fido2UIManager.renderDeviceManager({ + theme: { + logo: '/assets/my-logo.png', + primaryColor: '#ce59d9', + backgroundColor: '#ffffff' + } +}); +``` + +### 完整主题定制 + +```javascript +Fido2UIManager.renderDeviceManager({ + theme: { + logo: '/assets/my-logo.png', + primaryColor: '#0066cc', + backgroundColor: '#f8f9fa', + textColor: '#333333', + borderRadius: '12px' + } +}); +``` + +### 深色主题示例 + +```javascript +Fido2UIManager.renderDeviceManager({ + theme: { + logo: '/assets/logo.png', + primaryColor: '#4a9eff', + backgroundColor: '#1a1a2e', + textColor: '#ffffff', + borderRadius: '8px' + } +}); +``` + +--- + +## 设备管理器实例方法 + +如果需要访问设备管理器实例,可以保存 `renderDeviceManager` 的返回值: + +```javascript +const manager = Fido2UIManager.renderDeviceManager(config); +``` + +### 实例方法 + +| 方法 | 说明 | +|------|------| +| `close()` | 关闭模态框(仅 modal 模式) | +| `refresh()` | 刷新设备列表和会话状态 | +| `destroy()` | 销毁设备管理器实例 | + +### 示例 + +```javascript +const manager = Fido2UIManager.renderDeviceManager({ + container: '#device-container', + mode: 'modal' +}); + +// 手动刷新 +manager.refresh(); + +// 关闭模态框 +manager.close(); + +// 销毁实例 +manager.destroy(); +``` + +--- + +## CSS 类名 + +SDK 使用以下 CSS 类名,可以通过 CSS 覆盖样式: + +| 类名 | 说明 | +|------|------| +| `.fido2-sdk-modal` | 模态框容器 | +| `.fido2-sdk-card` | 卡片容器 | +| `.fido2-sdk-header` | 头部区域 | +| `.fido2-sdk-container` | 内容容器 | +| `.fido2-sdk-body` | 主体内容 | +| `.fido2-sdk-text` | 文字样式 | +| `.fido2-sdk-table` | 表格样式 | +| `.fido2-sdk-btn` | 按钮样式 | +| `.fido2-sdk-btn-primary` | 主要按钮样式 | +| `.fido2-sdk-status-badge` | 状态徽章样式 | +| `.fido2-sdk-user-info` | 用户信息样式 | +| `.fido2-sdk-standalone` | 独立页面样式 | +| `.fido2-sdk-logo` | Logo 样式 | + +### 自定义 CSS 示例 + +```css +/* 自定义按钮样式 */ +.fido2-sdk-btn-primary { + background-color: #ff6b6b !important; + font-weight: bold; +} + +/* 自定义表格样式 */ +.fido2-sdk-table th { + font-size: 14px; + color: #666; +} + +/* 自定义模态框样式 */ +.fido2-sdk-modal .modal-content { + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); +} +``` + +--- + +## 类型定义 + +### ConfigObject + +```typescript +interface ConfigObject { + serverUrl?: string; + mode?: 'modal' | 'standalone'; + container?: string | Element; + theme?: ThemeObject; + language?: string; + customI18n?: Record>; + features?: FeaturesObject; + callbacks?: CallbacksObject; + rpId?: string | null; + autoRefresh?: boolean; + refreshInterval?: number; +} +``` + +### ThemeObject + +```typescript +interface ThemeObject { + logo?: string | null; + primaryColor?: string; + backgroundColor?: string; + textColor?: string; + borderRadius?: string; +} +``` + +### FeaturesObject + +```typescript +interface FeaturesObject { + showAddButton?: boolean; + showDeleteButton?: boolean; + showUserInfo?: boolean; + showSessionStatus?: boolean; +} +``` + +### CallbacksObject + +```typescript +interface CallbacksObject { + onInit?: (manager: any) => void; + onDeviceAdded?: (device: any) => void; + onDeviceDeleted?: (deviceId: string) => void; + onDeviceListLoaded?: (devices: any[]) => void; + onError?: (error: Error) => void; + onClose?: () => void; +} +``` + +--- + +## 常见问题 + +### Q: 如何在页面加载后自动打开设备管理器? + +```javascript +window.onload = function() { + Fido2UIManager.renderDeviceManager({ + container: '#device-container', + mode: 'modal' + }); +}; +``` + +### Q: 如何在用户点击按钮后才打开设备管理器? + +```html + +
+ + +``` + +### Q: 如何禁用自动刷新? + +```javascript +Fido2UIManager.renderDeviceManager({ + autoRefresh: false +}); +``` + +### Q: 如何更改刷新间隔? + +```javascript +Fido2UIManager.renderDeviceManager({ + autoRefresh: true, + refreshInterval: 10000 // 10秒 +}); +``` + +--- + +## 版本历史 + +- **v1.0.0** - 初始版本 + - 支持模态框和独立页面两种模式 + - 支持主题定制 + - 支持国际化 + - 完整的事件系统 diff --git a/docs/IMPLEMENTATION_SUMMARY.md b/docs/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..c9c2ceb --- /dev/null +++ b/docs/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,270 @@ +# FIDO2 UI SDK - 实施总结 + +## 创建的文件 + +### 核心 SDK 文件 +- `files/fido2-ui-sdk.js` (27KB) - 核心 JavaScript SDK +- `files/fido2-ui-sdk.css` (4.5KB) - SDK 样式文件 + +### 演示文件 +- `modal-demo.html` (9.0KB) - 模态框模式演示 +- `standalone-demo.html` (8.9KB) - 独立页面模式演示 + +### 文档文件 +- `docs/README.md` (7.6KB) - 使用文档 +- `docs/API.md` (13KB) - API 参考文档 + +## 项目结构 + +``` +sample-site/ +├── files/ +│ ├── fido2-lib.js (现有,核心 FIDO2 库) +│ ├── fido2-ui-sdk.js (新增 - SDK 核心) +│ ├── fido2-ui-sdk.css (新增 - SDK 样式) +│ └── (其他现有文件保持不变) +├── modal-demo.html (新增 - 模态框模式演示) +├── standalone-demo.html (新增 - 独立页面模式演示) +├── devices.html (现有 - 保持不变) +├── login.html (现有 - 保持不变) +└── docs/ + ├── README.md (新增 - 使用指南) + └── API.md (新增 - API 文档) +``` + +## 功能特性 + +### ✅ 已实现的功能 + +1. **双模式支持** + - 模态框模式 (Modal): 在当前页面弹出设备管理窗口 + - 独立页面模式 (Standalone): 渲染完整的设备管理页面 + +2. **主题定制** + - Logo 自定义 + - 主色调 (primaryColor) + - 背景色 (backgroundColor) + - 文字颜色 (textColor) + - 圆角 (borderRadius) + +3. **国际化** + - 内置中文、英文、日文 + - 支持自定义翻译 + - 根据浏览器语言自动切换 + +4. **功能开关** + - 显示/隐藏添加按钮 + - 显示/隐藏删除按钮 + - 显示/隐藏用户信息 + - 显示/隐藏会话状态 + +5. **事件系统** + - 初始化完成 (init) + - 设备添加成功 (deviceAdded) + - 设备删除成功 (deviceDeleted) + - 设备列表加载 (deviceListLoaded) + - 会话状态改变 (sessionStatusChanged) + - 错误发生 (error) + - 窗口关闭 (close) + +6. **自动刷新** + - 支持自动刷新设备列表 + - 可配置刷新间隔 + +7. **响应式设计** + - 支持桌面端和移动端 + - 自适应布局 + +## 使用方法 + +### 模态框模式(推荐) + +```html + + + + + + + + + + + +
+ + +``` + +### 独立页面模式 + +```javascript +Fido2UIManager.renderDeviceManager({ + mode: 'standalone', + serverUrl: 'https://fido2.amipro.me' +}); +``` + +### 带主题定制 + +```javascript +Fido2UIManager.renderDeviceManager({ + container: '#device-container', + mode: 'modal', + serverUrl: 'https://fido2.amipro.me', + theme: { + logo: '/assets/my-logo.png', + primaryColor: '#ce59d9', + backgroundColor: '#ffffff' + }, + language: 'zh-CN' +}); +``` + +### 带事件回调 + +```javascript +Fido2UIManager.renderDeviceManager({ + container: '#device-container', + mode: 'modal', + serverUrl: 'https://fido2.amipro.me', + callbacks: { + onInit: function(manager) { + console.log('初始化完成'); + }, + onDeviceAdded: function(device) { + console.log('设备添加成功:', device); + // 刷新用户界面 + }, + onDeviceDeleted: function(deviceId) { + console.log('设备删除成功:', deviceId); + } + } +}); +``` + +## API 方法 + +| 方法 | 说明 | +|------|------| +| `Fido2UIManager.renderDeviceManager(config)` | 渲染设备管理器 | +| `Fido2UIManager.close()` | 关闭模态框(仅 modal 模式) | +| `Fido2UIManager.refresh()` | 刷新设备列表和会话状态 | +| `Fido2UIManager.destroy()` | 销毁设备管理器实例 | + +## 向后兼容性 + +✅ **完全兼容现有对接方式** + +- `devices.html` - 继续使用现有逻辑,无需修改 +- `login.html` - 继续使用现有逻辑,无需修改 +- `dfido2-lib.js` - 核心库保持不变 +- 所有现有的 CSS 和 JavaScript 文件保持不变 + +## 浏览器支持 + +- Chrome 67+ +- Firefox 60+ +- Safari 13+ +- Edge 18+ + +## 依赖要求 + +- jQuery 3.x +- Bootstrap 5.x +- Popper.js +- dfido2-lib.js(核心 FIDO2 库) +- UA-Parser.js(设备描述解析) + +## 演示 + +### 模态框模式演示 +访问 `modal-demo.html` 查看模态框模式的演示 + +### 独立页面模式演示 +访问 `standalone-demo.html` 查看独立页面模式的演示 + +## 文档 + +详细文档请查看: +- `docs/README.md` - 使用指南和快速开始 +- `docs/API.md` - 完整的 API 参考文档 + +## 下一步建议 + +1. **测试功能** + - 在浏览器中打开 `modal-demo.html` 测试模态框模式 + - 在浏览器中打开 `standalone-demo.html` 测试独立页面模式 + - 测试添加、删除设备功能 + - 测试主题定制功能 + - 测试国际化功能 + +2. **集成到现有项目** + - 在您的页面中引入 SDK + - 根据需求选择模式(modal 或 standalone) + - 配置主题和回调函数 + - 测试所有功能 + +3. **自定义开发** + - 根据需要调整样式 + - 添加自定义翻译 + - 扩展事件处理逻辑 + - 集成到现有用户管理系统 + +## 注意事项 + +1. 确保 `dfido2-lib.js` 在 `fido2-ui-sdk.js` 之前加载 +2. 模态框模式需要提供有效的容器选择器 +3. 独立页面模式会替换当前页面的内容 +4. 确保浏览器支持 WebAuthn API +5. 确保所有依赖文件(jQuery、Bootstrap 等)都已正确加载 + +## 技术架构 + +### 模块组成 + +1. **I18nManager** - 国际化管理 + - 支持多语言 + - 支持自定义翻译 + - 自动语言检测 + +2. **EventManager** - 事件管理 + - 发布-订阅模式 + - 支持多个监听器 + - 事件触发和冒泡 + +3. **ThemeManager** - 主题管理 + - CSS 变量注入 + - 动态样式应用 + - 样式清理 + +4. **DeviceManager** - 设备管理 + - 加载设备列表 + - 添加/删除设备 + - 会话状态检查 + - 自动刷新 + +5. **UIRenderer** - UI 渲染 + - 模态框渲染 + - 独立页面渲染 + - 设备列表更新 + - 事件绑定 + +6. **Fido2UIManager** - 主管理器 + - 配置管理 + - 模块协调 + - API 暴露 + +## 许可证 + +[根据您的项目许可证填写] + +## 联系方式 + +如有问题或建议,请联系 [您的联系方式] diff --git a/docs/LOGIN_SDK.md b/docs/LOGIN_SDK.md new file mode 100644 index 0000000..f5d57f2 --- /dev/null +++ b/docs/LOGIN_SDK.md @@ -0,0 +1,270 @@ +# Fido2Login SDK API 文档 + +## 概述 + +`Fido2UIManager.renderLogin()` 是一个用于渲染登录组件的API,支持: +- Fido2/Passkey 自动登录 +- 密码登录回退 +- 密码重试次数限制 +- 完全的回调驱动(SDK不跳转页面) + +## 使用方法 + +### 1. 引入依赖 + +```html + + + + +``` + +### 2. 添加容器 + +```html +
+``` + +### 3. 初始化登录组件 + +```javascript +const loginManager = Fido2UIManager.renderLogin({ + container: '#login-container', + features: { + autoAuth: true, + enablePasswordLogin: true, + maxPasswordAttempts: 3, + showRemainingAttempts: true + }, + callbacks: { + onFido2Success: (userId, session) => { + // 处理Fido2登录成功 + }, + onFido2Error: (error) => { + // 处理Fido2登录失败 + }, + onPasswordLogin: (userId, password) => { + // 返回 Promise + }, + onPasswordExhausted: (userId, attempts, maxAttempts) => { + // 密码重试次数耗尽 + }, + onLoginClosed: () => { + // UI被关闭 + } + } +}); +``` + +## 配置参数 + +### container +- **类型**: `string | Element` +- **必填**: 是 +- **说明**: 模态框容器元素 + +### features +- **类型**: `Object` +- **默认值**: 见下方 + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `autoAuth` | boolean | true | 有注册设备时自动Fido2登录 | +| `enablePasswordLogin` | boolean | true | 是否启用密码登录功能 | +| `autoShowPassword` | boolean | false | Fido2失败后是否自动显示密码框 | +| `maxPasswordAttempts` | number | 3 | 密码最大重试次数 | +| `showRemainingAttempts` | boolean | true | 是否显示剩余尝试次数 | + +### theme +- **类型**: `Object` +- **说明**: 复用 `renderDeviceManager` 的theme配置 + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `logo` | string | null | Logo图片URL | +| `primaryColor` | string | '#696cff' | 主色调 | +| `backgroundColor` | string | '#ffffff' | 背景色 | +| `textColor` | string | '#333333' | 文字颜色 | +| `borderRadius` | string | '8px' | 边框圆角 | + +### language +- **类型**: `string` +- **默认值**: `'zh-CN'` +- **说明**: 支持9种语言 + +### callbacks + +#### onFido2Success(userId, session) +- **触发时机**: Fido2登录认证成功 +- **参数**: + - `userId`: string - 用户ID + - `session`: object - 会话信息 +- **注意**: SDK不跳转页面,由调用端处理跳转 + +#### onFido2Error(error) +- **触发时机**: Fido2登录失败或取消 +- **参数**: `error` 对象 + - `code`: string - 错误码 + - `message`: string - 错误信息 + - `originalError`: object - 原始错误 + +**error.code 值**: +| code | 说明 | +|------|------| +| `CANCELED` | 用户取消认证 | +| `AUTH_FAILED` | 认证失败 | +| `NO_REGISTRATION` | 无注册设备且未启用密码登录 | +| `NOT_SUPPORTED` | 浏览器不支持WebAuthn | + +#### onPasswordLogin(userId, password) +- **触发时机**: 用户点击密码登录按钮 +- **参数**: + - `userId`: string - 用户ID + - `password`: string - 密码 +- **返回值**: `Promise` + - `true`: 登录成功 + - `false`: 登录失败 + +#### onPasswordExhausted(userId, attempts, maxAttempts) +- **触发时机**: 密码重试次数耗尽 +- **参数**: + - `userId`: string - 用户ID + - `attempts`: number - 已尝试次数 + - `maxAttempts`: number - 最大允许次数 +- **注意**: UI已自动关闭 + +#### onLoginClosed() +- **触发时机**: 用户关闭模态框(点击×或调用hide()) + +## 实例方法 + +### show() +显示登录模态框 + +### hide() +隐藏登录模态框,触发 `onLoginClosed` 回调 + +### destroy() +销毁登录组件实例,不触发任何回调 + +### setMode(mode) +切换登录模式 +- `mode`: `'fido2'` 或 `'password'` + +### getUserId() +获取当前输入的用户ID + +### getState() +获取当前状态 +- 返回值: `'loading'` | `'fido2'` | `'password'` | `'closed'` + +### getMode() +获取当前模式 +- 返回值: `'fido2'` | `'password'` + +### getAttemptCount() +获取当前密码尝试次数 + +### getRemainingAttempts() +获取剩余尝试次数 + +### resetPasswordAttempts() +重置密码尝试计数器 + +## 国际化支持 + +默认支持9种语言: +- `en-US` (英语) +- `zh-CN` (简体中文) +- `ja` (日语) +- `es` (西班牙语) +- `de` (德语) +- `fr` (法语) +- `pt` (葡萄牙语) +- `ko` (韩语) +- `ru` (俄语) +- `it` (意大利语) + +可通过 `customI18n` 配置自定义文本: +```javascript +Fido2UIManager.renderLogin({ + customI18n: { + 'title_login': { + 'en-US': 'Custom Login', + 'zh-CN': '自定义登录' + } + } +}); +``` + +## 完整示例 + +```html + + + + Login Example + + + + + + + +
+ + + + +``` + +## 版本信息 + +- **FIDO2 UI SDK**: v1.0.0+ +- **文件**: `files/fido2-ui-sdk.js` +- **新增功能**: `Fido2UIManager.renderLogin()` diff --git a/files/fido2-ui-sdk.js b/files/fido2-ui-sdk.js index ccffd69..f684aaa 100644 --- a/files/fido2-ui-sdk.js +++ b/files/fido2-ui-sdk.js @@ -1468,6 +1468,23 @@ Fido2Login.prototype._getWebAuthnErrorMessage = function(error) { if (!error) return this.i18n.getText('msg_fido2_failed'); + // Check for browser-native WebAuthn errors with URL references + const errorMessage = error.message || ''; + if (errorMessage.includes('https://www.w3.org/TR/webauthn')) { + // Check for common browser-native error patterns + if (error.name === 'NotAllowedError' || errorMessage.toLowerCase().includes('not allowed')) { + return this.i18n.getText('error_not_allowed'); + } + if (errorMessage.toLowerCase().includes('timeout') || errorMessage.toLowerCase().includes('timed out')) { + return this.i18n.getText('error_timeout'); + } + if (errorMessage.toLowerCase().includes('invalid state') || errorMessage.toLowerCase().includes('already registered')) { + return this.i18n.getText('error_invalid_state'); + } + // Default to not allowed for browser privacy errors + return this.i18n.getText('error_not_allowed'); + } + const i18nKey = this._getWebAuthnErrorI18nKey(error); if (i18nKey && this.i18n.getText(i18nKey)) { return this.i18n.getText(i18nKey); @@ -2421,6 +2438,22 @@ const errorMessage = error.message || ''; const errorName = error.name || ''; + // Check for browser-native WebAuthn errors with URL references + if (errorMessage.includes('https://www.w3.org/TR/webauthn')) { + // Check for common browser-native error patterns + if (errorName === 'NotAllowedError' || errorMessage.toLowerCase().includes('not allowed')) { + return this.i18n.getText('error_not_allowed'); + } + if (errorMessage.toLowerCase().includes('timeout') || errorMessage.toLowerCase().includes('timed out')) { + return this.i18n.getText('error_timeout'); + } + if (errorMessage.toLowerCase().includes('invalid state') || errorMessage.toLowerCase().includes('already registered')) { + return this.i18n.getText('error_invalid_state'); + } + // Default to not allowed for browser privacy errors + return this.i18n.getText('error_not_allowed'); + } + // Check WebAuthn DOM error name first if (errorName && this._getWebAuthnErrorI18nKey) { const i18nKey = this._getWebAuthnErrorI18nKey(error); diff --git a/modal-demo.html b/modal-demo.html index b040e7f..983cf5b 100644 --- a/modal-demo.html +++ b/modal-demo.html @@ -181,7 +181,7 @@ - + diff --git a/sso.html b/sso.html new file mode 100644 index 0000000..9877ac5 --- /dev/null +++ b/sso.html @@ -0,0 +1,131 @@ + + + + + + amiPro SSO + + + + + +
+

amiPro Passkey SSO Beta

+

Use passkeys to sign in. Choose production or your ngrok dev host.

+ +
+ + +
+ + + +

Current server: (not set)

+ + + + + + + + + + + + + +
+
+ + diff --git a/test-device-manager.html b/test-device-manager.html new file mode 100644 index 0000000..151b99b --- /dev/null +++ b/test-device-manager.html @@ -0,0 +1,260 @@ + + + + + + FIDO2 Device Manager Test + + + + + + + +
+

FIDO2 Device Manager Test

+ + + +
+ + +
+ +
+ +
+ + +
+
+ + +
+
+ + + + + + +
+ + + +
+ + + + diff --git a/test-device-recovery.html b/test-device-recovery.html new file mode 100644 index 0000000..73ba504 --- /dev/null +++ b/test-device-recovery.html @@ -0,0 +1,239 @@ + + + + + + FIDO2 Device Recovery Test + + + + + + + +
+

FIDO2 Device Recovery Test

+ + + +
+

Recovery Mode

+

Use this mode when user clicks a recovery link with ?rid=xxx parameter.

+ +
+ + +
+ + +
+ +
+

Auto-detect Recovery from URL

+

Add ?rid=YOUR_SESSION_ID to the URL and refresh the page.

+ +
+ +
+ + + +
+ + + + diff --git a/test-login-sdk.html b/test-login-sdk.html new file mode 100644 index 0000000..1bb86ab --- /dev/null +++ b/test-login-sdk.html @@ -0,0 +1,316 @@ + + + + + + Fido2 Login SDK Test + + + + + + +
+
+
+
+
+

Fido2 Login SDK 测试

+
+ + 检查中... +
+
+
+
+
+
+
+
设备注册测试
+
+ +
+
+ +
+
+ 💡 提示:使用新User ID注册可测试自动登录流程 +
+ + +
+
+
+
+
+
+
登录组件测试
+ + + +
+ 未启动 +
+
+
+
+
+ +
+ +
测试日志:
+
+
+
+
+
+
+
+ +
+ + + + + + + + +