授权服务(@uniboot/auth)
与框架无关的 OAuth 2.0 登录状态机与路由权限守卫,将 登录 一文中的授权中心跳转、换票、路由拦截沉淀为可复用能力。账号资料、忘记密码等由 @uniboot/admin 负责。
| 能力 | 导出 | 说明 |
|---|---|---|
| OAuth 状态机 | createOAuthAuthService | state 防伪、code 换票、401 刷新 |
| 路由权限守卫 | setupAuthPermissionGuard | 未登录重定向、OAuth 回调、动态路由、白名单 |
| 登录 API | createAuthApi | /auth/login、/oauth/logout(本地表单场景) |
| 页面组件 | AuthLoginPage | 本地登录表单(不走 SSO 整页跳转时用) |
类型以 XxxLike 描述宿主 router / user,不直接依赖具体版本的 vue-router。peerDependencies:vue、vue-i18n、uniboot-ui。dependencies:@uniboot/request。
Auth 模板接入
三服务地址均需配置(与 用户服务 一致):
| 环境变量 | 含义 | 鉴权侧用法 |
|---|---|---|
APP_PUBLIC_API_URL | 业务系统 | 默认 request |
APP_PUBLIC_AUTH_SERVICE_URL | 授权服务 | Bundle → authHttp;OAuth 换票 / 刷新 |
APP_PUBLIC_ADMIN_SERVICE_URL | 用户服务 | Bundle → adminHttp(见 admin 文档) |
模板职责拆分:
| 文件 | 职责 |
|---|---|
src/utils/request.ts | createUnibootAdminHttpBundle 创建 authHttp / adminHttp 与各 API |
src/setup/auth-runtime.ts | HTTP 公共配置、OAuth 实例、setupPermissionGuard、401 刷新(不含 admin 安装) |
src/router/guard/permission.ts | 调用 setupPermissionGuard |
src/install/plugins/uniboot-admin.ts | 直接调用 setupUnibootAdmin(见 用户服务) |
// src/setup/auth-runtime.ts(节选)
oauthAuthService = createOAuthAuthService({
authServiceUrl: config.authServiceUrl,
appBase: config.appBase,
redirectUri: config.redirectUri,
clientId: config.clientId,
http, // 与守卫共用;401 刷新也走同一实例
tokenPath: '/oauth/token',
refreshTokenPath: '/oauth/refresh_token',
})
setupAuthPermissionGuard({
router,
oauth: oauthAuthService,
useAuthServiceLogin: Boolean(config.authServiceUrl?.trim()),
user: createAuthPermissionUserBridge(),
// loginPath / whiteList / dynamicRoutes / progress / feedback ...
})// src/router/guard/permission.ts
import { setupPermissionGuard } from '@/setup/auth-runtime'
import request from '@/utils/request'
export default function createPermissionGuard(router: Router) {
setupPermissionGuard(router, request)
}refreshHttpAccessToken(HTTP 401 拦截器)与守卫共用同一个 oauthAuthService,登录 / 刷新 / 路由拦截的 token 语义一致。须在 createRouter 之后、app.use(router) 之前注册守卫。
createOAuthAuthService
把「统一授权中心登录」拆成纯函数,中间状态默认写入 sessionStorage(可换 OAuthStorageLike)。
参数
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| authServiceUrl | 授权中心地址 | string | — |
| appBase | 应用基础路径,用于推导 redirectUri | string | — |
| redirectUri | 回调地址;未传按 ${origin}${appBase} 推导 | string | 按 appBase 推导 |
| clientId | OAuth 客户端 ID | string | 'koms' |
| scope | 授权范围 | string | 'user_info' |
| http | 换票 / 刷新用的 HTTP 客户端 | object | — |
| tokenPath | 换票路径 | string | '/oauth/token' |
| refreshTokenPath | 刷新路径 | string | '/oauth/refresh_token' |
| state | 防伪校验值 | string | OAUTH_FIXED_STATE('STATE') |
| storage | 中间状态存储 | object | sessionStorage |
| getOrigin | 推导 redirectUri 时取源 | function | () => location.origin |
返回值
| 名称 | 说明 | 类型 |
|---|---|---|
| buildAuthorizeHref | 生成授权中心 /login URL,并写入 state | function |
| rememberReturnPath | 记忆登录前地址 | function |
| takeAndClearReturnPath | 取出并清除返回地址 | function |
| getLoginState | 读取已写入的 state | function |
| exchangeAuthorizationCode | code 换 { accessToken, refreshToken? } | function |
| refreshAccessToken | refresh token 换新令牌对 | function |
| clearLoginSessionMarkers | 清理 state / 返回地址 | function |
实现细节
- 未显式传
state时用固定值'STATE':授权中心是整页跳转,SPA 无法跨跳转共享内存;固定值 +sessionStorage足以满足同源 CSRF 防护。 - 令牌解析兼容
access_token/accessToken、顶层或嵌套在result/data、以及 JSON 字符串;响应含error时抛出error_description。
setupAuthPermissionGuard
组装 router.beforeEach:访问拦截 → 授权中心 → 回调换票 → 动态路由。
参数
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| router | 满足 AuthPermissionRouterLike 即可 | object | — |
| user | token / 用户信息 / 路由表适配器 | object | — |
| dynamicRoutes | 首页路由、路由名、首个可用路由查找 | object | — |
| loginPath | 登录页路径 | string | — |
| indexPath | 首页路径 | string | — |
| error403Path | 无权限页路径 | string | — |
| whiteList | 免登录白名单 | array | — |
| title | document.title 回退 | string / function | — |
| useAuthServiceLogin | 是否整页跳转授权中心 | boolean | false |
| oauth | createOAuthAuthService 实例 | object | — |
| tabs | 动态路由挂载后设置多标签路由名 | object | — |
| progress | 进度条钩子 | object | — |
| feedback | 错误提示 | object | — |
| redirectTo | 跳转授权中心 | function | window.location.href |
| isExternal | 外链判断,动态挂载时跳过 | function | 匹配 http(s): / mailto: / tel: |
执行流程
- OAuth 回调(URL 带
code且未登录):校验error/state→ 换票写 token →takeAndClearReturnPath跳回。 - 白名单:放行;若目标是
loginPath且启用了useAuthServiceLogin,记忆redirect后跳转授权中心。 - 已登录:有用户信息则放行;否则
loadUserInfo→ 挂动态路由 →next({ ...to, replace: true });失败则清登录态回登录页。 - 未登录且未启用 OAuth:跳转本地登录页并带
redirect。 - 未登录且启用 OAuth:记忆地址后整页跳转授权中心,
next(false)。
createAuthApi
本地表单登录场景(Auth 模板默认走 SSO,通常不直接用)。
参数
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| http | HTTP 客户端 | object | — |
| paths | 部分覆盖 defaultAuthApiPaths | object | login: '/auth/login'、logout: '/oauth/logout' |
方法
| 名称 | 说明 | 类型 |
|---|---|---|
| login | 默认 withToken: false;可用 login<T>() 指定返回类型 | function |
| logout | 登出 | function |
useLoginAccount({ api }) 把 LoginPage 表单值映射为登录请求(trim 用户名并透传验证码)。
AuthLoginPage
不启用 useAuthServiceLogin、在前端渲染登录表单时使用。内部已接 useLoginAccount;写 token、跳转仍由宿主在 onFinish 中完成。Auth 模板默认 SSO,不引用该组件。
属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| api | createAuthApi 实例 | object | — |
| logo | Logo URL | string | — |
| illustration | 插画 URL | string | — |
| onFinish | 登录成功回调;result 为 api.login 返回值 | function | — |
| showCaptcha | 是否展示验证码 | boolean | false |
| getCaptcha | 获取验证码 | function | — |
| initialValues | 初始表单值 | object | — |
事件 / 插槽
| 名称 | 说明 |
|---|---|
language-change | 语言切换 |
#actions / #footer | 表单下方 / 左侧底部 |
i18n
mergeUnibootAuthLocales(i18n) 合并 authLocaleZhCn / authLocaleEn 到 zh_CN/zh-CN、en_US/en-US。命名空间为 unibootAuth.login.*。Auth 模板在 uniboot-admin 安装插件里与 admin 文案一并处理;账号域更多文案见 @uniboot/admin。