Basic Auth 守卫
本指南介绍如何使用 HTTP Basic 身份验证协议对 HTTP 请求进行身份验证。你将学习:
- basic 身份验证的工作原理以及何时使用它
- 如何配置 basic auth 守卫和用户提供者
- 如何使用 basic auth 对请求进行身份验证
- 如何使用 auth 中间件保护路由
概述
Basic auth 守卫实现了
HTTP 身份验证框架
。客户端在每个请求的 Authorization 头中以 base64 编码字符串的形式发送凭据。例如,Authorization: Basic am9obkBleGFtcGxlLmNvbTpzZWNyZXQ= 包含了用户的邮箱和密码。
Basic 身份验证是无状态的,因为服务器不维护任何持久化的 session,也不签发令牌。相反,客户端必须在每个请求中都包含凭据。由于凭据是明文发送的(仅做了 base64 编码),在生产环境中 basic 身份验证必须始终通过 HTTPS 使用。
虽然 basic 身份验证设置简单,但由于缺乏 MFA 或账户管理等现代安全特性,不推荐用于生产应用。它主要用于早期开发阶段或简单的内部工具。
配置守卫
首先,在你的 config/auth.ts 文件中定义 basic auth 守卫。你必须从 @adonisjs/auth/basic_auth 模块导入 basicAuthGuard 和 basicAuthUserProvider。
import { defineConfig } from '@adonisjs/auth'
import { basicAuthGuard, basicAuthUserProvider } from '@adonisjs/auth/basic_auth'
const authConfig = defineConfig({
default: 'basic',
guards: {
basic: basicAuthGuard({
provider: basicAuthUserProvider({
model: () => import('#models/user'),
}),
}),
},
})
export default authConfig
basicAuthUserProvider 使用你的 User 模型来查找和验证凭据。它期望该模型拥有一个 verifyCredentials 静态方法,该方法通常由
AuthFinder mixin
提供。
配置 User 模型
basicAuthUserProvider 可与任何代表你用户实体的 Lucid 模型配合使用。在安装过程中,add 命令会生成一个应用了 withAuthFinder mixin 的 User 模型。
import { DateTime } from 'luxon'
import { compose } from '@adonisjs/core/helpers'
import { BaseModel, column } from '@adonisjs/lucid/orm'
import hash from '@adonisjs/core/services/hash'
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid'
/**
* 应用 withAuthFinder mixin 会向你的模型添加
* verifyCredentials 静态方法。
*/
const AuthFinder = withAuthFinder(() => hash.use('scrypt'), {
uids: ['email'],
passwordColumnName: 'password',
})
export default class User extends compose(BaseModel, AuthFinder) {
@column({ isPrimary: true })
declare id: number
@column()
declare email: string
@column()
declare password: string
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime
}
对请求进行身份验证
客户端必须包含 Authorization 头,形式为 Basic 一词,后跟一个空格,以及 base64 编码的凭据(通常是 email:password)。
Authorization: Basic am9obkBleGFtcGxlLmNvbTpzZWNyZXQ=
使用 auth 中间件
将 auth 中间件应用到需要身份验证的路由。该中间件会自动读取头信息,使用配置的提供者验证凭据,并将用户附加到 HTTP 上下文。
import { middleware } from '#start/kernel'
import router from '@adonisjs/core/services/router'
router
.get('/projects', async ({ auth }) => {
/**
* 现在 auth.user 属性就是已身份验证的用户。
* 使用 auth.getUserOrFail() 以避免非空断言。
*/
const user = auth.getUserOrFail()
return user.related('projects').query()
})
.use(middleware.auth({ guards: ['basic'] }))
如果凭据缺失或无效,中间件会抛出 E_UNAUTHORIZED_ACCESS 异常。
手动身份验证
要在不使用中间件的情况下进行身份验证,可调用 auth.authenticate() 或 auth.authenticateUsing()。
router.get('/projects', async ({ auth }) => {
/**
* 使用默认守卫进行身份验证。
* 失败时抛出 E_UNAUTHORIZED_ACCESS。
*/
const user = await auth.authenticate()
return user.related('projects').query()
})
Basic 身份验证会在 每个 请求上执行一次数据库查询和密码验证。与基于 session 或令牌的身份验证相比,这在计算上开销很大。如果性能是关注点,随着应用规模增长,请考虑迁移到 Session 守卫 或 Access tokens 守卫 。
下一步
- 验证用户凭据 :了解 User 模型如何处理密码验证。
- Session 守卫 :适用于 Web 应用的基于 cookie 的身份验证。
- Access tokens 守卫 :适用于 API 和移动应用的基于令牌的身份验证。