更新文档

This commit is contained in:
Eric
2026-02-10 17:24:47 +08:00
parent 2c8995653a
commit 6b6a728cf9
12 changed files with 1827 additions and 586 deletions

View File

@@ -1,10 +1,8 @@
## 安装
```bash
npm install unified-login-sdk --save
npm install oauth2-login-sdk --save
# 或
yarn add unified-login-sdk
yarn add oauth2-login-sdk
```
## 快速开始
@@ -12,522 +10,61 @@ yarn add unified-login-sdk
### 基本使用
```typescript
import unifiedLoginSDK from 'unified-login-sdk';
// main.ts
import unifiedLoginSDK from "oauth2-login-sdk"
// 初始化配置
unifiedLoginSDK.init({
clientId: 'your-client-id',
authorizationEndpoint: 'https://auth.example.com/authorize',
tokenEndpoint: 'https://auth.example.com/token',
userInfoEndpoint: 'https://auth.example.com/userinfo',
redirectUri: 'https://your-app.example.com/callback',
storageType: 'localStorage',
autoRefreshToken: true,
tenantId: 'your-tenant-id' // 可选会自动添加到请求头中的tenant-id字段
});
// 登录
document.getElementById('login-btn')?.addEventListener('click', () => {
unifiedLoginSDK.login();
});
// 处理回调
if (unifiedLoginSDK.isAuthenticated()) {
// 已登录,获取用户信息
unifiedLoginSDK.getUserInfo().then(userInfo => {
console.log('User info:', userInfo);
});
} else if (unifiedLoginSDK.isCallback()) {
// 处理授权回调
unifiedLoginSDK.handleCallback().then(userInfo => {
console.log('Login successful:', userInfo);
// 跳转到首页
window.location.href = '/';
}).catch(error => {
console.error('Login failed:', error);
});
}
// 退出登录
document.getElementById('logout-btn')?.addEventListener('click', () => {
unifiedLoginSDK.logout().then(() => {
console.log('Logout successful');
window.location.href = '/login';
});
});
clientId: import.meta.env.VITE_APP_CLIENT_ID,
registrationId: import.meta.env.VITE_APP_REGISTRATION_ID,
storageType: import.meta.env.VITE_APP_STORAGE_TYPE,
basepath: import.meta.env.VITE_APP_BASE_API,
idpLogoutUrl: import.meta.env.VITE_APP_IDP_LOGOUT_URL,
homePage: import.meta.env.VITE_APP_HOME_PAGE
})
```
```properties
# 配置文件
VITE_APP_CLIENT_ID=xxx
VITE_APP_REGISTRATION_ID=xxx
VITE_APP_STORAGE_TYPE=localStorage
VITE_APP_IDP_LOGOUT_URL=http://106.14.217.120/idp-ui/logout
VITE_APP_HOME_PAGE=http://106.14.217.120/portal-ui/index
```
## 核心功能
### 初始化配置
```typescript
unifiedLoginSDK.init({
clientId: 'your-client-id',
clientSecret: 'your-client-secret', // 可选,某些场景下需要
authorizationEndpoint: 'https://auth.example.com/authorize',
tokenEndpoint: 'https://auth.example.com/token',
userInfoEndpoint: 'https://auth.example.com/userinfo',
redirectUri: 'https://your-app.example.com/callback',
storageType: 'localStorage', // 可选默认localStorage
autoRefreshToken: true, // 可选默认true
permissionsEndpoint: 'https://auth.example.com/permissions' // 可选,权限端点
});
```
### 登录流程
1. 调用`login()`方法跳转到授权页面
2. 用户在授权页面登录并授权
3. 授权服务器重定向到配置的`redirectUri`
4. 调用`handleCallback()`方法处理授权回调,获取用户信息
### Token管理
```typescript
// 获取访问令牌
const accessToken = unifiedLoginSDK.getAccessToken();
// 刷新令牌
unifiedLoginSDK.refreshToken().then(() => {
console.log('Token refreshed');
}).catch(error => {
console.error('Failed to refresh token:', error);
});
// 检查是否已认证
const isAuthenticated = unifiedLoginSDK.isAuthenticated();
```
### 用户信息管理
```typescript
// 获取用户信息
unifiedLoginSDK.getUserInfo().then(userInfo => {
console.log('User info:', userInfo);
});
// 获取用户权限列表
unifiedLoginSDK.getPermissions().then(permissions => {
console.log('Permissions:', permissions);
});
```
### 事件监听
```typescript
// 监听登录事件
unifiedLoginSDK.on('login', () => {
console.log('User logged in');
});
// 监听退出事件
unifiedLoginSDK.on('logout', () => {
console.log('User logged out');
});
// 监听Token过期事件
unifiedLoginSDK.on('tokenExpired', () => {
console.log('Token expired');
// 可以在这里执行自定义逻辑,如跳转到登录页
unifiedLoginSDK.login();
});
// 移除事件监听
const handleLogin = () => console.log('User logged in');
unifiedLoginSDK.on('login', handleLogin);
unifiedLoginSDK.off('login', handleLogin);
```
## 框架集成
### Vue 2
```javascript
// main.js
import Vue from 'vue';
import { createVuePlugin } from 'unified-login-sdk';
import App from './App.vue';
import router from './router';
// 创建Vue插件
const vuePlugin = createVuePlugin('localStorage');
// 安装插件
Vue.use(vuePlugin, {
config: {
clientId: 'your-client-id',
authorizationEndpoint: 'https://auth.example.com/authorize',
tokenEndpoint: 'https://auth.example.com/token',
userInfoEndpoint: 'https://auth.example.com/userinfo',
redirectUri: 'https://your-app.example.com/callback'
}
});
new Vue({
router,
render: h => h(App)
}).$mount('#app');
```
在组件中使用:
```vue
<template>
<div>
<div v-if="$auth.isAuthenticated()">
<h1>Welcome, {{ userInfo?.name }}</h1>
<button @click="logout">Logout</button>
</div>
<div v-else>
<button @click="login">Login</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
userInfo: null
};
},
mounted() {
if (this.$auth.isAuthenticated()) {
this.getUserInfo();
} else if (this.$auth.isCallback()) {
this.handleCallback();
}
},
methods: {
login() {
this.$auth.login();
},
async logout() {
await this.$auth.logout();
window.location.href = '/';
},
async getUserInfo() {
this.userInfo = await this.$auth.getUserInfo();
},
async handleCallback() {
try {
this.userInfo = await this.$auth.handleCallback();
window.location.href = '/';
} catch (error) {
console.error('Login failed:', error);
}
}
}
};
</script>
```
### Vue 3
```javascript
// main.js
import { createApp } from 'vue';
import { createVuePlugin } from 'unified-login-sdk';
import App from './App.vue';
import router from './router';
// 创建Vue插件
const vuePlugin = createVuePlugin('localStorage');
const app = createApp(App);
// 安装插件
app.use(vuePlugin, {
config: {
clientId: 'your-client-id',
authorizationEndpoint: 'https://auth.example.com/authorize',
tokenEndpoint: 'https://auth.example.com/token',
userInfoEndpoint: 'https://auth.example.com/userinfo',
redirectUri: 'https://your-app.example.com/callback'
}
});
app.use(router);
app.mount('#app');
```
在组件中使用Composition API
```vue
<template>
<div>
<div v-if="isAuthenticated">
<h1>Welcome, {{ userInfo?.name }}</h1>
<button @click="logout">Logout</button>
</div>
<div v-else>
<button @click="login">Login</button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, inject } from 'vue';
// 注入SDK实例
const auth = inject('unifiedLogin');
const userInfo = ref(null);
const isAuthenticated = ref(auth.isAuthenticated());
onMounted(() => {
if (isAuthenticated.value) {
getUserInfo();
} else if (auth.isCallback()) {
handleCallback();
}
});
const login = () => {
auth.login();
};
const logout = async () => {
await auth.logout();
window.location.href = '/';
};
const getUserInfo = async () => {
userInfo.value = await auth.getUserInfo();
};
const handleCallback = async () => {
try {
userInfo.value = await auth.handleCallback();
isAuthenticated.value = true;
window.location.href = '/';
} catch (error) {
console.error('Login failed:', error);
}
};
</script>
```
```
## API参考
### 初始化
```typescript
init(config: SDKConfig): void
```
初始化SDK配置。
### 登录
```typescript
login(redirectUri?: string): void
```
触发登录流程,可选参数`redirectUri`可覆盖初始化时的配置。
### 退出登录
```typescript
logout(): Promise<void>
```
退出登录清除本地存储的Token和用户信息。
### 处理授权回调
```typescript
handleCallback(): Promise<UserInfo>
```
处理授权回调,获取用户信息。
### 获取用户信息
```typescript
getUserInfo(): Promise<UserInfo>
```
获取用户基本信息。
### 获取用户权限列表
```typescript
getPermissions(): Promise<string[]>
```
获取用户权限列表。
### 检查是否已认证
```typescript
isAuthenticated(): boolean
```
检查用户是否已认证。
### 获取访问令牌
```typescript
getAccessToken(): string | null
```
获取访问令牌。
### 刷新访问令牌
```typescript
refreshToken(): Promise<void>
```
刷新访问令牌。
### 事件监听
```typescript
on(event: 'login' | 'logout' | 'tokenExpired', callback: Function): void
```
监听登录、退出或Token过期事件。
### 移除事件监听
```typescript
off(event: 'login' | 'logout' | 'tokenExpired', callback: Function): void
```
移除事件监听。
## 配置选项
| 选项 | 类型 | 必填 | 默认值 | 描述 |
|------|------|------|--------|------|
| clientId | string | 是 | - | 客户端ID |
| clientSecret | string | 否 | - | 客户端密钥,某些场景下需要 |
| authorizationEndpoint | string | 是 | - | 授权端点URL |
| tokenEndpoint | string | 是 | - | Token端点URL |
| userInfoEndpoint | string | 是 | - | 用户信息端点URL |
| redirectUri | string | 是 | - | 重定向URL |
| storageType | 'localStorage' 'sessionStorage' 'cookie' | 否 | 'localStorage' | Token存储类型 |
| autoRefreshToken | boolean | 否 | true | 是否自动刷新Token |
| permissionsEndpoint | string | 否 | - | 权限端点URL |
| stateLength | number | 否 | 32 | 状态参数长度 |
| tenantId | string | 否 | - | 租户ID会自动添加到请求头中的tenant-id字段 |
## 事件处理
| 事件 | 描述 |
|------|------|
| login | 用户登录成功时触发 |
| logout | 用户退出登录时触发 |
| tokenExpired | Token过期时触发 |
## 路由守卫
### Vue路由守卫
```javascript
// router/index.js
import VueRouter from 'vue-router';
import { Auth } from 'unified-login-sdk';
import { Storage } from 'unified-login-sdk';
import { RouterGuard } from 'unified-login-sdk';
const storage = new Storage('localStorage');
const auth = new Auth(storage);
const routerGuard = new RouterGuard(auth);
const router = new VueRouter({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/protected',
name: 'Protected',
component: Protected,
meta: {
auth: {
requiresAuth: true,
requiredPermissions: ['read:protected']
// 配置路由导航守卫
router.beforeEach(async (to, _from, next) => {
// 打开页面 判断是已认证
if (!unifiedLoginSDK.isAuthenticated()) {
// 未认证
if (to.path === '/oauth2/callback') {
// 如果是登录回调 进行回调登录
await unifiedLoginSDK.handleCallback()
}else{
// 跳转登录
await unifiedLoginSDK.login()
}
}
} else {
//已认证 打开页面
next()
}
]
});
})
// 添加路由守卫
router.beforeEach(routerGuard.createVueGuard());
export default router;
```
## 错误处理
### 网络错误处理
```typescript
try {
await unifiedLoginSDK.getUserInfo();
} catch (error) {
if (error.name === 'HttpError') {
// 处理HTTP错误
console.error('HTTP Error:', error.status, error.message);
if (error.status === 401) {
// 未授权,跳转到登录页
unifiedLoginSDK.login();
} else if (error.status === 403) {
// 权限不足
window.location.href = '/403';
// 请求后端接口添加token
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 10000
})
// request拦截器
import unifiedLoginSDK from "oauth2-login-sdk"
service.interceptors.request.use((config: any) => {
if (getToken() && !isToken) {
config.headers['Authorization'] = unifiedLoginSDK.getToken()
}
} else {
// 处理其他错误
console.error('Error:', error.message);
}
}
})
```
### Token失效处理
```typescript
// 监听Token过期事件
unifiedLoginSDK.on('tokenExpired', () => {
console.log('Token expired');
// 跳转到登录页
unifiedLoginSDK.login();
});
```
## 最佳实践
1. **配置安全存储**根据项目需求选择合适的存储类型敏感信息建议使用cookie并设置secure和httpOnly标志。
2. **合理设置Token过期时间**根据项目安全性要求设置合适的Token过期时间建议access token过期时间较短refresh token过期时间较长。
3. **使用路由守卫保护敏感路由**:对需要登录或特定权限的路由使用路由守卫进行保护。
4. **处理网络错误**在调用SDK方法时使用try-catch捕获并处理可能的错误。
5. **监听Token过期事件**及时处理Token过期情况避免用户体验下降。
6. **不要直接暴露clientSecret**clientSecret应该只在后端使用前端SDK尽量避免使用clientSecret。
7. **使用HTTPS**确保所有与授权服务器的通信都使用HTTPS避免Token被窃取。
8. **定期清理存储**:在用户退出登录时,确保清理所有相关存储的信息。
## 浏览器兼容性
- Chrome (推荐)
- Firefox
- Safari
- Edge
## 许可证
MIT License