fix(api): 后端自动串联WordPress认证

This commit is contained in:
sunlei 2026-05-17 17:24:47 +08:00
parent c0ab04e521
commit c8541facd4
5 changed files with 20 additions and 6 deletions

10
API.md
View File

@ -57,7 +57,7 @@ Admin、Component、Dict 与 MinIO 业务接口统一走 `JwtAuthGuard`。请求
### WordPress 认证透传 ### WordPress 认证透传
WordPress 侧只使用客户端登录态,后端不走 BasicAuth。当前 WordPress 只有单管理员账号且不开放注册,管理员账号配置放在 env 中,`/wordpress/auth/login` 会在 Admin 登录成功后使用该账号自动登录 WordPress把 WordPress cookie 保存到本系统 httpOnly cookie再把 REST nonce 和用户信息返回给前端持久化。 WordPress 侧只使用客户端登录态,后端不走 BasicAuth。当前 WordPress 只有单管理员账号且不开放注册,管理员账号配置放在 env 中,Admin 调用 `/auth/login` 通过后,后端会在同一个登录流程里自动登录 WordPress把 WordPress cookie 保存到本系统 httpOnly cookie再把 REST nonce 和用户信息随 Admin 登录结果返回给前端持久化。
环境变量: 环境变量:
@ -325,9 +325,9 @@ Query
| 方法 | 路径 | 说明 | | 方法 | 路径 | 说明 |
| --- | --- | --- | | --- | --- | --- |
| POST | `/auth/login` | 登录,返回 `accessToken`,并写入 access token 与刷新 token cookie | | POST | `/auth/login` | 登录,返回 `accessToken``wordpressAuth`,并写入 access token、刷新 token 和 WordPress 授权 cookie |
| POST | `/auth/refresh` | 通过刷新 token cookie 刷新 accessToken并更新 token cookie | | POST | `/auth/refresh` | 通过刷新 token cookie 刷新 accessToken并更新 token cookie |
| POST | `/auth/logout` | 退出登录并清理 access token 与刷新 token cookie | | POST | `/auth/logout` | 退出登录并清理 access token、刷新 token 与 WordPress 授权 cookie |
| GET | `/auth/codes` | 获取当前用户权限码 | | GET | `/auth/codes` | 获取当前用户权限码 |
| GET | `/user/info` | 获取当前用户信息 | | GET | `/user/info` | 获取当前用户信息 |
| GET | `/menu/all` | 获取当前用户可访问菜单 | | GET | `/menu/all` | 获取当前用户可访问菜单 |
@ -362,11 +362,11 @@ Query
## WordPress 接口 ## WordPress 接口
所有 `/wordpress/*` 管理接口都需要本系统后台登录态和 WordPress 客户端登录态。Admin 登录通过后会自动调用 `/wordpress/auth/login` 建立 WordPress 授权态;后端只把 WordPress cookie 保存到本系统 httpOnly cookie不把 cookie 明文放入前端持久化。 所有 `/wordpress/*` 管理接口都需要本系统后台登录态和 WordPress 客户端登录态。Admin 前端只调用现有 `/auth/login`,后端在该登录接口内部自动建立 WordPress 授权态;后端只把 WordPress cookie 保存到本系统 httpOnly cookie不把 cookie 明文放入前端持久化。
### POST `/wordpress/auth/login` ### POST `/wordpress/auth/login`
使用 env 中的 `WORDPRESS_ADMIN_USERNAME``WORDPRESS_ADMIN_PASSWORD` 登录 WordPress写入 `kt_wordpress_auth` httpOnly cookie并返回前端需要持久化的 REST nonce 和 WordPress 当前用户信息。 使用 env 中的 `WORDPRESS_ADMIN_USERNAME``WORDPRESS_ADMIN_PASSWORD` 登录 WordPress写入 `kt_wordpress_auth` httpOnly cookie并返回前端需要持久化的 REST nonce 和 WordPress 当前用户信息。该接口主要保留为后端内部能力和调试口子,正常 Admin 登录链路不由前端主动调用它,而是通过 `/auth/login` 自动触发。
响应 `data` 响应 `data`

View File

@ -113,7 +113,7 @@ pnpm test:e2e # e2e 测试
- 如果旧版本曾写入 `admin_user.id=0`,先执行 `sql/fix-admin-user-zero-id.sql` 修复脏数据,再重启服务。 - 如果旧版本曾写入 `admin_user.id=0`,先执行 `sql/fix-admin-user-zero-id.sql` 修复脏数据,再重启服务。
- Admin、Component、Dict 与 MinIO 业务接口统一走 `JwtAuthGuard`;登录、刷新 token、退出登录和部分示例状态测试接口通过 `@Public()` 放行。 - Admin、Component、Dict 与 MinIO 业务接口统一走 `JwtAuthGuard`;登录、刷新 token、退出登录和部分示例状态测试接口通过 `@Public()` 放行。
- WordPress 管理接口同样先走本系统 `JwtAuthGuard`,再透传客户端 WordPress 登录态访问 WordPress REST API当前 WordPress 只有单管理员账号且不开放注册,账号配置放在 env 中,但不作为 BasicAuth 发送。 - WordPress 管理接口同样先走本系统 `JwtAuthGuard`,再透传客户端 WordPress 登录态访问 WordPress REST API当前 WordPress 只有单管理员账号且不开放注册,账号配置放在 env 中,但不作为 BasicAuth 发送。
- Admin 登录成功后会调用 `/wordpress/auth/login` 自动登录 WordPress后端把 WordPress cookie 写入本系统 httpOnly cookie前端只持久化 REST nonce 和用户信息。 - Admin 前端只调用现有 `/auth/login`;后端会在登录流程里自动登录 WordPress把 WordPress cookie 写入本系统 httpOnly cookie前端只持久化 REST nonce 和用户信息。
- WordPress 客户端登录态优先通过 `X-WordPress-Authorization` 透传,也支持 `X-WP-Nonce` 加 WordPress 登录 cookie 的 REST cookie 认证。 - WordPress 客户端登录态优先通过 `X-WordPress-Authorization` 透传,也支持 `X-WP-Nonce` 加 WordPress 登录 cookie 的 REST cookie 认证。
- 如果 WordPress 服务器未开启 rewrite 导致 `/wp-json/*` 返回 404后端会自动回退到 `?rest_route=/...` 形式继续访问 REST API。 - 如果 WordPress 服务器未开启 rewrite 导致 `/wp-json/*` 返回 404后端会自动回退到 `?rest_route=/...` 形式继续访问 REST API。
- `kt-template-admin` 登录会写入 access token 与刷新 token cookie`kt-template-online-web` 和 `kt-template-online-playground` 可在回跳后通过刷新 token 重新持久化登录态。 - `kt-template-admin` 登录会写入 access token 与刷新 token cookie`kt-template-online-web` 和 `kt-template-online-playground` 可在回跳后通过刷新 token 重新持久化登录态。

View File

@ -23,6 +23,7 @@ import { AdminUser } from './user/admin-user.entity';
import { AdminUserService } from './user/admin-user.service'; import { AdminUserService } from './user/admin-user.service';
import { ToolsService } from '@/common'; import { ToolsService } from '@/common';
import { MinioClientModule } from '@/minio/minio.module'; import { MinioClientModule } from '@/minio/minio.module';
import { WordpressModule } from '@/wordpress/wordpress.module';
@Module({ @Module({
imports: [ imports: [
@ -36,6 +37,7 @@ import { MinioClientModule } from '@/minio/minio.module';
AdminAuthGuardModule, AdminAuthGuardModule,
DictModule, DictModule,
MinioClientModule, MinioClientModule,
WordpressModule,
], ],
controllers: [ controllers: [
AdminAuthController, AdminAuthController,

View File

@ -15,6 +15,7 @@ import { AdminUser } from '../user/admin-user.entity';
import { AdminUserService } from '../user/admin-user.service'; import { AdminUserService } from '../user/admin-user.service';
import { AdminAuthService } from './admin-auth.service'; import { AdminAuthService } from './admin-auth.service';
import { JwtAuthGuard } from './jwt-auth.guard'; import { JwtAuthGuard } from './jwt-auth.guard';
import { WordpressService } from '@/wordpress/wordpress.service';
@ApiTags('admin-auth') @ApiTags('admin-auth')
@Controller() @Controller()
@ -24,6 +25,7 @@ export class AdminAuthController {
private readonly authService: AdminAuthService, private readonly authService: AdminAuthService,
private readonly menuService: AdminMenuService, private readonly menuService: AdminMenuService,
private readonly userService: AdminUserService, private readonly userService: AdminUserService,
private readonly wordpressService: WordpressService,
) {} ) {}
@Post('auth/login') @Post('auth/login')
@ -36,11 +38,19 @@ export class AdminAuthController {
body.username, body.username,
body.password, body.password,
); );
const wordpressLogin =
await this.wordpressService.loginWithConfiguredAdmin();
this.authService.setAccessTokenCookie(res, accessToken); this.authService.setAccessTokenCookie(res, accessToken);
this.authService.setRefreshTokenCookie(res, refreshToken); this.authService.setRefreshTokenCookie(res, refreshToken);
this.wordpressService.setAuthCookie(res, wordpressLogin.cookie);
return vbenSuccess({ return vbenSuccess({
...this.userService.serializeUser(user), ...this.userService.serializeUser(user),
accessToken, accessToken,
wordpressAuth: {
...wordpressLogin.auth,
user: wordpressLogin.user,
},
}); });
} }
@ -62,6 +72,7 @@ export class AdminAuthController {
logout(@Res({ passthrough: true }) res: Response) { logout(@Res({ passthrough: true }) res: Response) {
this.authService.clearAccessTokenCookie(res); this.authService.clearAccessTokenCookie(res);
this.authService.clearRefreshTokenCookie(res); this.authService.clearRefreshTokenCookie(res);
this.wordpressService.clearAuthCookie(res);
return vbenSuccess(''); return vbenSuccess('');
} }

View File

@ -16,5 +16,6 @@ import { WordpressTagController } from './wordpress-tag.controller';
WordpressCategoryController, WordpressCategoryController,
], ],
providers: [ToolsService, WordpressService], providers: [ToolsService, WordpressService],
exports: [WordpressService],
}) })
export class WordpressModule {} export class WordpressModule {}