静默授权功能解耦方案.md
7.73 KB
静默授权功能解耦方案
当前功能分析
核心功能
静默授权功能主要包含以下核心能力:
-
静默授权 -
silentAuth()函数,自动获取微信授权并保存会话信息 -
授权状态检查 -
needAuth()函数,检查是否需要重新授权 - 页面路径管理 - 保存和恢复用户访问路径
- 授权重定向 - 授权完成后的页面跳转逻辑
- 分享页面处理 - 处理从分享链接进入的授权逻辑
当前耦合点分析
1. 项目特定依赖
-
路由存储: 依赖
@/stores/router(Pinia store) -
网络请求: 依赖
@/utils/request(axios封装) -
业务API: 依赖
@/api/family(家庭相关接口) -
页面路径: 硬编码了项目特定的页面路径
-
/pages/Dashboard/index(首页) -
/pages/Welcome/index(欢迎页) -
/pages/auth/index(授权页)
-
2. 业务逻辑耦合
-
家庭状态检查:
checkUserHasFamily()函数与业务强耦合 - 跳转逻辑: 根据家庭状态决定跳转目标的业务逻辑
- 测试环境配置: 硬编码的测试openid列表
3. 框架依赖
- Taro框架: 使用Taro的API进行页面跳转和存储操作
- 微信小程序: 依赖微信小程序的wx API
解耦方案
方案一:配置化解耦(推荐)
创建一个通用的授权管理器,通过配置参数来适配不同项目。
1. 核心授权管理器
// auth-manager.js
export class AuthManager {
constructor(config) {
this.config = {
// 授权接口配置
authUrl: '/srv/?a=openid',
// 页面路径配置
authPage: '/pages/auth/index',
defaultPage: '/pages/index/index',
// 存储配置
sessionKey: 'sessionid',
routeKey: 'saved_route',
// 测试环境配置
testOpenIds: [],
// 自定义钩子函数
onAuthSuccess: null,
onAuthError: null,
checkUserStatus: null, // 用户状态检查函数
getRedirectPath: null, // 获取重定向路径函数
// 网络请求实例
httpClient: null,
...config
}
}
// 静默授权
async silentAuth(onSuccess, onError) {
// 实现逻辑...
}
// 检查授权状态
needAuth() {
// 实现逻辑...
}
// 页面跳转管理
async returnToOriginalPage(defaultPath) {
// 实现逻辑...
}
}
2. 项目适配配置
// 老来赛项目配置
import { getMyFamiliesAPI } from '@/api/family'
import request from '@/utils/request'
const authConfig = {
authPage: '/pages/auth/index',
defaultPage: '/pages/Dashboard/index',
httpClient: request,
testOpenIds: ['h-008', 'h-009', 'h-010'],
// 用户状态检查
async checkUserStatus() {
try {
const { code, data } = await getMyFamiliesAPI()
return code && data && data.length > 0
} catch (error) {
return false
}
},
// 获取重定向路径
async getRedirectPath(savedPath, defaultPath) {
const hasFamily = await this.checkUserStatus()
if (!hasFamily) {
return '/pages/Welcome/index'
}
return savedPath || defaultPath
}
}
export const authManager = new AuthManager(authConfig)
方案二:插件化解耦
将授权功能拆分为多个独立的插件模块。
1. 核心授权插件
// plugins/auth-core.js
export class AuthCore {
constructor(storage, http) {
this.storage = storage
this.http = http
}
async silentAuth(config) {
// 核心授权逻辑
}
needAuth(sessionKey = 'sessionid') {
// 授权状态检查
}
}
2. 路由管理插件
// plugins/route-manager.js
export class RouteManager {
constructor(storage, navigator) {
this.storage = storage
this.navigator = navigator
}
saveCurrentPath() {
// 保存当前路径
}
async returnToPath(pathResolver) {
// 返回指定路径
}
}
3. 业务适配插件
// plugins/business-adapter.js
export class BusinessAdapter {
constructor(apiClient) {
this.apiClient = apiClient
}
async checkUserStatus() {
// 业务相关的用户状态检查
}
resolveRedirectPath(userStatus, savedPath, defaultPath) {
// 根据业务逻辑解析重定向路径
}
}
方案三:抽象接口解耦
定义标准接口,让不同项目实现自己的适配器。
1. 定义抽象接口
// interfaces/auth-interfaces.js
export class IStorageAdapter {
get(key) { throw new Error('Not implemented') }
set(key, value) { throw new Error('Not implemented') }
remove(key) { throw new Error('Not implemented') }
}
export class IHttpAdapter {
post(url, data) { throw new Error('Not implemented') }
}
export class INavigatorAdapter {
navigateTo(url) { throw new Error('Not implemented') }
redirectTo(url) { throw new Error('Not implemented') }
reLaunch(url) { throw new Error('Not implemented') }
}
export class IBusinessAdapter {
async checkUserStatus() { throw new Error('Not implemented') }
resolveRedirectPath(savedPath, defaultPath) { throw new Error('Not implemented') }
}
2. Taro适配器实现
// adapters/taro-adapters.js
import Taro from '@tarojs/taro'
export class TaroStorageAdapter extends IStorageAdapter {
get(key) {
return wx.getStorageSync(key)
}
set(key, value) {
wx.setStorageSync(key, value)
}
remove(key) {
wx.removeStorageSync(key)
}
}
export class TaroNavigatorAdapter extends INavigatorAdapter {
navigateTo(url) {
return Taro.navigateTo({ url })
}
redirectTo(url) {
return Taro.redirectTo({ url })
}
reLaunch(url) {
return Taro.reLaunch({ url })
}
}
推荐实施步骤
第一步:提取核心功能
- 将
silentAuth和needAuth函数提取为独立模块 - 移除硬编码的页面路径和业务逻辑
- 通过参数传递配置信息
第二步:创建适配层
- 创建存储适配器(支持不同的存储方案)
- 创建网络请求适配器(支持不同的HTTP客户端)
- 创建导航适配器(支持不同的路由方案)
第三步:业务逻辑分离
- 将用户状态检查逻辑抽象为可配置的函数
- 将重定向逻辑抽象为策略模式
- 提供默认实现和自定义扩展点
第四步:打包发布
- 创建npm包,支持不同框架的适配器
- 提供详细的文档和示例
- 支持TypeScript类型定义
使用示例
在新项目中使用
// 安装
npm install @your-org/universal-auth
// 配置
import { AuthManager } from '@your-org/universal-auth'
import { TaroAdapters } from '@your-org/universal-auth/adapters/taro'
const authManager = new AuthManager({
...TaroAdapters,
authUrl: '/api/auth',
authPage: '/pages/login/index',
defaultPage: '/pages/home/index',
async checkUserStatus() {
// 项目特定的用户状态检查逻辑
const userInfo = await getUserInfo()
return userInfo.isActive
},
async getRedirectPath(savedPath, defaultPath) {
// 项目特定的重定向逻辑
const userStatus = await this.checkUserStatus()
return userStatus ? (savedPath || defaultPath) : '/pages/onboarding/index'
}
})
// 使用
await authManager.silentAuth()
总结
推荐使用方案一:配置化解耦,因为它:
- 实施成本最低 - 只需要重构现有代码,不需要重新设计架构
- 兼容性最好 - 保持现有功能不变,只是增加了配置能力
- 维护成本最低 - 一套代码支持多个项目,统一维护和升级
- 学习成本最低 - API保持基本不变,只需要了解配置选项
通过这种方式,你可以将静默授权功能打包成一个通用的npm包,在其他项目中只需要提供相应的配置参数即可快速集成。