翻译:
具有内置SSO支持的Bagelink应用程序的现代认证库,自动重定向处理,和Vue组件.
特征
- 🔐 完整认证流量 - 登录、注册、密码重置、电子邮件核查
- 🚀 SSO 准备 - 谷歌、GitHub、微软、苹果、奥克塔、Facebook
- 🔄 自动定向 - 自动处理登录后导航
- 🛡️ 内部安保 - 防止公开定向攻击
- 🎨 Vue 组件 - 预建表格和页面
- 📱 类型安全 - 全部类型脚本支持
- 🧩 路由器集成 - 保护路线的聪明警卫
安装
npm install @bagelink/auth
快速启动
1. 初始化 Auth
// main.ts
import { createApp } from 'vue'
import { createAuth } from '@bagelink/auth'
import router from './router'
const auth = createAuth({
baseURL: 'https://api.your-app.com',
redirect: {
loginRoute: 'Login',
fallback: '/dashboard',
autoRedirect: true, // Automatic post-login redirect
}
})
// Connect router (automatically sets up auth guard)
auth.use(router)
const app = createApp(App)
app.use(router)
app.use(auth) // Optional: adds $auth globally
app.mount('#app')
2. 界定路线
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
},
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue'),
meta: { auth: true }, // Protected route
},
]
export default createRouter({
history: createWebHistory(),
routes,
})
3. 组件的使用
<script setup lang="ts">
import { useAuth } from '@bagelink/auth'
const auth = useAuth()
async function handleLogin() {
await auth.login({
email: '[email protected]',
password: 'password'
})
// Auto-redirect happens automatically! 🎉
}
</script>
<template>
<div v-if="auth.user.value">
<p>Welcome, {{ auth.user.value.name }}!</p>
<button @click="auth.logout()">Logout</button>
</div>
</template>
文档
- (原始内容存档于2018-10-21). Redirect Guide.md - 完整的重定向配置指南
- 完整- EXAMPLE. md - 完整的应用实例
- 呼吸 变化.md - 打破变化的移徙指南
核心 API
createAuth(config)
初始化重定向配置的认证模块 :
createAuth({
baseURL: string, // Required: Your API base URL
redirect?: {
loginRoute?: string, // Login route name (default: 'Login')
fallback?: string, // Default redirect after login (default: '/')
queryKey?: string, // Query param for redirect URL (default: 'redirect')
autoRedirect?: boolean, // Auto-redirect after login (default: true)
preserveRedirect?: boolean, // Preserve original URL (default: true)
noAuthRoutes?: string[], // Routes requiring no auth (default: ['Login', 'Signup', ...])
allowedPaths?: RegExp[], // Optional: Restrict allowed redirects for security
}
})
useAuth()
返回可与 :
{
// State
user: Ref<User | null>
accountInfo: Ref<AccountInfo | null>
// Authentication
login(credentials): Promise<AuthenticationResponse>
signup(data): Promise<AuthenticationResponse>
logout(): Promise<void>
checkAuth(): Promise<boolean>
// SSO
sso: {
google: { redirect(), callback() }
github: { redirect(), callback() }
microsoft: { redirect(), callback() }
// ... more providers
}
// Password Management
forgotPassword(email): Promise<void>
resetPassword(token, newPassword): Promise<void>
changePassword(current, new): Promise<void>
// Profile
updateProfile(updates): Promise<void>
// Getters
getFullName(): string
getIsLoggedIn(): boolean
getEmail(): string
getRoles(): string[]
}
自定义后卫构成
对于多租户应用程序或高级许可逻辑,可禁用自动守护并自编曲:
备选案文1:使用 composeGuards 工具( 建议)
import { composeGuards } from '@bagelink/auth'
// Disable auto-guard
auth.use(router, { guard: false })
// Custom org access guard
const orgAccessGuard = () => async (to, from, next) => {
if (to.meta.requiresOrg) {
const hasAccess = await checkOrgAccess(to.params.orgId)
if (!hasAccess) return next('/no-access')
}
next()
}
// Compose all guards in sequence
router.beforeEach(composeGuards([
auth.routerGuard(), // Auth first
orgAccessGuard(), // Then org check
]))
备选案文2:多重 beforeEach 电话
auth.use(router, { guard: false })
// Guards run in order they're registered
router.beforeEach(auth.routerGuard())
router.beforeEach(async (to, from, next) => {
// Custom org/tenant check
if (to.meta.requiresOrg && !await checkOrgAccess(to.params.orgId)) {
return next('/no-access')
}
next()
})
备选办法3:手工组成
auth.use(router, { guard: false })
router.beforeEach(async (to, from, next) => {
// Run auth guard first
const authPassed = await new Promise<boolean>((resolve) => {
auth.routerGuard()(to, from, (result?: any) => {
if (result !== undefined) {
next(result)
resolve(false)
} else {
resolve(true)
}
})
})
if (!authPassed) return
// Your custom logic
if (to.meta.requiresOrg && !await checkOrgAccess(to.params.orgId)) {
return next('/no-access')
}
next()
})
构成部分
预建页面
<script setup>
import { LoginPage, SignupPage, ForgotPasswordPage } from '@bagelink/auth'
</script>
<template>
<LoginPage
:texts="{ title: 'Welcome Back' }"
card-width="400px"
/>
</template>
窗体组件
对于自定义布局 :
<script setup>
import { LoginForm, SignupForm } from '@bagelink/auth'
</script>
<template>
<div class="custom-layout">
<LoginForm
:texts="{ title: 'Sign In' }"
:show-google="true"
:show-github="true"
/>
</div>
</template>
SSO 整合
快速SSO 登录
const { sso } = useAuth()
// Redirect to Google OAuth
await sso.google.redirect({
redirect_uri: `${window.location.origin}/auth/callback`
})
SSO 回调路由
// router.ts
{
path: '/auth/callback',
name: 'AuthCallback',
component: () => import('@bagelink/auth').then(m => m.Callback),
}
现有供应商
- 谷歌
- GitHub 图像
- 微软
- 苹果公司
- 奥克塔
- 脸书
SSO 重定向保存
当用户访问受保护的路由并通过SSO认证时,会自动保存原始的URL:
// User tries to access /dashboard (protected)
// ↓ Redirected to /login?redirect=/dashboard
// ↓ User clicks "Login with Google"
// ↓ Goes to Google OAuth
// ↓ Returns to /auth/callback
// ↓ Automatically redirected to /dashboard ✅
如何运作:
- 这个
redirect查询参数存储于sessionStorage在SSO重定向前 - OAuth 回电后恢复到 URL
- 自动重定向( 或手动倒置) 使用它来导航到原目的地
具有方向的手动SSO :
// On login page with ?redirect=/dashboard
await sso.google.redirect()
// Redirect param is automatically preserved across the OAuth flow
高级配置
安全性:限制方向路径
createAuth({
baseURL: 'https://api.example.com',
redirect: {
allowedPaths: [
/^\/dashboard/,
/^\/profile/,
/^\/settings/,
],
// Only these paths can be redirect targets
}
})
禁用自动重定向
对于自定义逻辑 :
createAuth({
redirect: {
autoRedirect: false, // Manual control
}
})
// Then in login handler:
import { performRedirect, getRedirectConfig } from '@bagelink/auth'
await auth.login(credentials)
await performRedirect(router, getRedirectConfig())
自定义路由Meta 密钥
createAuth({
redirect: {
authMetaKey: 'requiresAuth', // Default: 'auth'
}
})
// Then in routes:
{
path: '/dashboard',
meta: { requiresAuth: true } // Custom meta key
}
事件系统
听从认证事件 :
import { createAuth, AuthState } from '@bagelink/auth'
const auth = createAuth({ ... })
auth.on(AuthState.LOGIN, () => {
console.log('User logged in')
})
auth.on(AuthState.LOGOUT, () => {
console.log('User logged out')
})
auth.on(AuthState.PROFILE_UPDATE, () => {
console.log('Profile updated')
})
可用事件 :
LOGINLOGOUTSIGNUPPASSWORD_RESETPASSWORD_CHANGEPROFILE_UPDATEAUTH_CHECKEMAIL_VERIFIEDSESSION_REFRESH
类型脚本支持
完整类型的定义包括:
import type {
User,
AccountInfo,
AuthState,
SSOProvider,
RedirectConfig,
LoginTexts,
SignupTexts,
} from '@bagelink/auth'
实例
保护路线流
- 用户访问
/dashboard(保护) - 未经认证 + 重新定向到
/login?redirect=/dashboard - 用户日志在
- 自动重定向到
/dashboard
自定义登录页面
<script setup lang="ts">
import { ref } from 'vue'
import { useAuth } from '@bagelink/auth'
const auth = useAuth()
const email = ref('')
const password = ref('')
const error = ref('')
async function handleLogin() {
try {
await auth.login({ email: email.value, password: password.value })
// Auto-redirect happens automatically!
} catch (err: any) {
error.value = err.response?.data?.message || 'Login failed'
}
}
</script>
<template>
<form @submit.prevent="handleLogin">
<input v-model="email" type="email" placeholder="Email" />
<input v-model="password" type="password" placeholder="Password" />
<button type="submit">Login</button>
<p v-if="error" class="error">{{ error }}</p>
</form>
</template>
基于角色的获取
import { useAuth } from '@bagelink/auth'
const auth = useAuth()
// Check if user has admin role
if (auth.getRoles().includes('admin')) {
// Allow access
}
// Or in route guard
router.beforeEach((to, from, next) => {
if (to.meta.requiresAdmin && !auth.getRoles().includes('admin')) {
next('/unauthorized')
} else {
next()
}
})
移徙
见 呼吸 变化.md 用于以往版本的移徙指南.
许可证
麻省理工学院