基于AdonisJS V6的多模型身份认证实现需求
AdonisJS V6 多模型认证(User/Admin分离)实现步骤
以下是针对AdonisJS V6(@adonisjs/core": "^6.17.2")和@adonisjs/auth": "^9.3.1"版本的多模型认证实现方案,完全分离User和Admin两个独立模型的认证流程:
1. 修改认证配置文件(config/auth.ts)
在配置文件中分别定义守卫(Guards)和提供者(Providers),对应User和Admin模型:
import { defineConfig } from '@adonisjs/auth' import { InferAuthEvents, Authenticators } from '@adonisjs/auth/types' const authConfig = defineConfig({ default: 'user', // 默认守卫,可按需调整 guards: { // User模型对应的JWT守卫 user: { driver: 'jwt', publicKey: env.get('JWT_PUBLIC_KEY'), privateKey: env.get('JWT_PRIVATE_KEY'), provider: { driver: 'lucid', identifierKey: 'id', uids: ['email'], model: () => import('#models/user'), }, tokenProvider: { type: 'api', driver: 'database', table: 'auth_tokens', }, expiresIn: '30d', }, // Admin模型对应的JWT守卫 admin: { driver: 'jwt', publicKey: env.get('JWT_PUBLIC_KEY'), privateKey: env.get('JWT_PRIVATE_KEY'), provider: { driver: 'lucid', identifierKey: 'id', uids: ['email'], model: () => import('#models/admin'), }, tokenProvider: { type: 'api', driver: 'database', table: 'auth_tokens', // 可共用表,也可单独创建admin_auth_tokens表 }, expiresIn: '7d', }, }, }) export default authConfig export type AuthenticatorKeys = keyof Authenticators<typeof authConfig> export type AuthEvents = InferAuthEvents<typeof authConfig>
2. 为模型添加认证特质
User模型(app/Models/User.ts)
实现认证契约并添加HasAuthTokens特质:
import { DateTime } from 'luxon' import { BaseModel, column } from '@adonisjs/lucid/orm' import { hash } from '@adonisjs/core/services' import { Authenticatable, AuthenticatableContract, HasAuthTokens } from '@adonisjs/auth/mixins' const AuthMixin = Authenticatable(() => import('@adonisjs/auth'), { passwordColumnName: 'password', }) export default class User extends BaseModel implements AuthenticatableContract { @column({ isPrimary: true }) public id: number @column() public email: string @column({ serializeAs: null }) public password: string @column.dateTime({ autoCreate: true }) public createdAt: DateTime @column.dateTime({ autoCreate: true, autoUpdate: true }) public updatedAt: DateTime // 混入认证相关方法 public static super = AuthMixin(User) public $hasAuthTokens = HasAuthTokens @column.dateTime() public passwordChangedAt: DateTime | null public async verifyPassword(password: string): Promise<boolean> { return hash.verify(this.password, password) } }
Admin模型(app/Models/Admin.ts)
同样配置认证特质:
import { DateTime } from 'luxon' import { BaseModel, column } from '@adonisjs/lucid/orm' import { hash } from '@adonisjs/core/services' import { Authenticatable, AuthenticatableContract, HasAuthTokens } from '@adonisjs/auth/mixins' const AuthMixin = Authenticatable(() => import('@adonisjs/auth'), { passwordColumnName: 'password', }) export default class Admin extends BaseModel implements AuthenticatableContract { @column({ isPrimary: true }) public id: number @column() public email: string @column({ serializeAs: null }) public password: string @column.dateTime({ autoCreate: true }) public createdAt: DateTime @column.dateTime({ autoCreate: true, autoUpdate: true }) public updatedAt: DateTime public static super = AuthMixin(Admin) public $hasAuthTokens = HasAuthTokens @column.dateTime() public passwordChangedAt: DateTime | null public async verifyPassword(password: string): Promise<boolean> { return hash.verify(this.password, password) } }
3. 创建认证控制器
用户登录控制器(app/Controllers/Http/UserAuthController.ts)
import type { HttpContext } from '@adonisjs/core/http' export default class UserAuthController { async login({ request, auth, response }: HttpContext) { const { email, password } = request.only(['email', 'password']) try { // 使用user守卫验证并生成token const token = await auth.use('user').attempt(email, password) return response.ok({ token, user: token.user }) } catch { return response.unauthorized('邮箱或密码错误') } } async logout({ auth, response }: HttpContext) { await auth.use('user').revoke() return response.ok({ message: '用户已退出登录' }) } }
管理员登录控制器(app/Controllers/Http/AdminAuthController.ts)
import type { HttpContext } from '@adonisjs/core/http' export default class AdminAuthController { async login({ request, auth, response }: HttpContext) { const { email, password } = request.only(['email', 'password']) try { // 使用admin守卫验证并生成token const token = await auth.use('admin').attempt(email, password) return response.ok({ token, admin: token.user }) } catch { return response.unauthorized('邮箱或密码错误') } } async logout({ auth, response }: HttpContext) { await auth.use('admin').revoke() return response.ok({ message: '管理员已退出登录' }) } }
4. 配置认证路由
在start/routes.ts中添加路由,并指定对应的守卫中间件:
import router from '@adonisjs/core/services/router' const UserAuthController = () => import('#controllers/http/user_auth_controller') const AdminAuthController = () => import('#controllers/http/admin_auth_controller') // 用户认证路由 router.group(() => { router.post('/login', [UserAuthController, 'login']) router.post('/logout', [UserAuthController, 'logout']).use('auth:user') }).prefix('/api/user/auth') // 管理员认证路由 router.group(() => { router.post('/login', [AdminAuthController, 'login']) router.post('/logout', [AdminAuthController, 'logout']).use('auth:admin') }).prefix('/api/admin/auth')
5. 验证多模型认证
现在你可以通过以下方式调用认证方法:
- 用户登录:发送POST请求到
/api/user/auth/login,传入email和password,成功后返回token - 管理员登录:发送POST请求到
/api/admin/auth/login,传入email和password,成功后返回token - 在需要验证用户身份的路由中使用
auth:user中间件,管理员则用auth:admin - 在控制器中通过
auth.use('user').user获取当前登录用户,auth.use('admin').user获取当前登录管理员
内容的提问来源于stack exchange,提问作者Sakil
相关产品推荐
相关产品推荐

