feat(admin): 串联WordPress自动认证

This commit is contained in:
sunlei 2026-05-17 16:45:19 +08:00
parent 46452a5117
commit 88310e0ee1
4 changed files with 112 additions and 1 deletions

View File

@ -16,6 +16,25 @@ export namespace AuthApi {
data: string; data: string;
status: number; status: number;
} }
export interface WordpressAuthResult {
auth: {
nonce: string;
type: 'cookie';
};
user?: Record<string, any>;
}
}
interface ApiSuccessResponse<T> {
code: number;
data: T;
msg: string;
}
interface RawApiResponse<T> {
data: ApiSuccessResponse<T>;
status: number;
} }
/** /**
@ -53,6 +72,36 @@ export async function logoutApi() {
); );
} }
/**
* WordPress
*/
export async function wordpressLoginApi() {
const response = await baseRequestClient.post<
RawApiResponse<AuthApi.WordpressAuthResult>
>(
'/wordpress/auth/login',
{},
{
withCredentials: true,
},
);
return response.data.data;
}
/**
* WordPress
*/
export async function wordpressLogoutApi() {
return baseRequestClient.post(
'/wordpress/auth/logout',
{},
{
withCredentials: true,
},
);
}
/** /**
* *
*/ */

View File

@ -50,6 +50,7 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) {
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
accessStore.setAccessToken(null); accessStore.setAccessToken(null);
accessStore.setWordpressAuth(null);
if ( if (
preferences.app.loginExpiredMode === 'modal' && preferences.app.loginExpiredMode === 'modal' &&
accessStore.isAccessChecked accessStore.isAccessChecked
@ -80,12 +81,18 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) {
fulfilled: async (config) => { fulfilled: async (config) => {
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const token = formatToken(accessStore.accessToken); const token = formatToken(accessStore.accessToken);
const wordpressNonce = accessStore.wordpressAuth?.nonce;
if (token) { if (token) {
config.headers.Authorization = token; config.headers.Authorization = token;
} else { } else {
delete config.headers.Authorization; delete config.headers.Authorization;
} }
if (wordpressNonce && `${config.url || ''}`.includes('/wordpress/')) {
config.headers['X-WP-Nonce'] = wordpressNonce;
} else {
delete config.headers['X-WP-Nonce'];
}
config.headers['Accept-Language'] = preferences.app.locale; config.headers['Accept-Language'] = preferences.app.locale;
return config; return config;
}, },

View File

@ -10,7 +10,14 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { notification } from 'antdv-next'; import { notification } from 'antdv-next';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api'; import {
getAccessCodesApi,
getUserInfoApi,
loginApi,
logoutApi,
wordpressLoginApi,
wordpressLogoutApi,
} from '#/api';
import { $t } from '#/locales'; import { $t } from '#/locales';
export const useAuthStore = defineStore('auth', () => { export const useAuthStore = defineStore('auth', () => {
@ -61,6 +68,13 @@ export const useAuthStore = defineStore('auth', () => {
url.searchParams.set('ktUserInfo', JSON.stringify(userStore.userInfo)); url.searchParams.set('ktUserInfo', JSON.stringify(userStore.userInfo));
} }
if (accessStore.wordpressAuth) {
url.searchParams.set(
'ktWordpressAuth',
JSON.stringify(accessStore.wordpressAuth),
);
}
return url.toString(); return url.toString();
} catch { } catch {
return target; return target;
@ -108,11 +122,16 @@ export const useAuthStore = defineStore('auth', () => {
fetchUserInfo(), fetchUserInfo(),
getAccessCodesApi(), getAccessCodesApi(),
]); ]);
const wordpressAuth = await wordpressLoginApi();
userInfo = fetchUserInfoResult; userInfo = fetchUserInfoResult;
userStore.setUserInfo(userInfo); userStore.setUserInfo(userInfo);
accessStore.setAccessCodes(accessCodes); accessStore.setAccessCodes(accessCodes);
accessStore.setWordpressAuth({
...wordpressAuth.auth,
user: wordpressAuth.user,
});
if (accessStore.loginExpired) { if (accessStore.loginExpired) {
accessStore.setLoginExpired(false); accessStore.setLoginExpired(false);
@ -132,6 +151,20 @@ export const useAuthStore = defineStore('auth', () => {
}); });
} }
} }
} catch (error) {
accessStore.setAccessToken(null);
accessStore.setAccessCodes([]);
accessStore.setWordpressAuth(null);
userStore.setUserInfo(null);
try {
await wordpressLogoutApi();
await logoutApi();
} catch {
// 不做任何处理
}
throw error;
} finally { } finally {
loginLoading.value = false; loginLoading.value = false;
} }
@ -147,6 +180,12 @@ export const useAuthStore = defineStore('auth', () => {
if (isLoggingOut.value) return; // 正在登出中, 说明已进入循环, 直接返回. if (isLoggingOut.value) return; // 正在登出中, 说明已进入循环, 直接返回.
isLoggingOut.value = true; // 设置 标识 isLoggingOut.value = true; // 设置 标识
try {
await wordpressLogoutApi();
} catch {
// 不做任何处理
}
try { try {
await logoutApi(); await logoutApi();
} catch { } catch {
@ -156,6 +195,7 @@ export const useAuthStore = defineStore('auth', () => {
resetAllStores(); resetAllStores();
accessStore.setLoginExpired(false); accessStore.setLoginExpired(false);
accessStore.setWordpressAuth(null);
} }
// 回登录页带上当前路由地址 // 回登录页带上当前路由地址

View File

@ -6,6 +6,12 @@ import { acceptHMRUpdate, defineStore } from 'pinia';
type AccessToken = null | string; type AccessToken = null | string;
interface WordpressAuthState {
nonce: string;
type: 'cookie';
user?: Record<string, any>;
}
interface AccessState { interface AccessState {
/** /**
* *
@ -43,6 +49,10 @@ interface AccessState {
* accessToken * accessToken
*/ */
refreshToken: AccessToken; refreshToken: AccessToken;
/**
* WordPress WordPress cookie httpOnly cookie
*/
wordpressAuth: null | WordpressAuthState;
} }
/** /**
@ -94,6 +104,9 @@ export const useAccessStore = defineStore('core-access', {
setRefreshToken(token: AccessToken) { setRefreshToken(token: AccessToken) {
this.refreshToken = token; this.refreshToken = token;
}, },
setWordpressAuth(auth: null | WordpressAuthState) {
this.wordpressAuth = auth;
},
unlockScreen() { unlockScreen() {
this.isLockScreen = false; this.isLockScreen = false;
this.lockScreenPassword = undefined; this.lockScreenPassword = undefined;
@ -107,6 +120,7 @@ export const useAccessStore = defineStore('core-access', {
'accessCodes', 'accessCodes',
'isLockScreen', 'isLockScreen',
'lockScreenPassword', 'lockScreenPassword',
'wordpressAuth',
], ],
}, },
state: (): AccessState => ({ state: (): AccessState => ({
@ -119,6 +133,7 @@ export const useAccessStore = defineStore('core-access', {
lockScreenPassword: undefined, lockScreenPassword: undefined,
loginExpired: false, loginExpired: false,
refreshToken: null, refreshToken: null,
wordpressAuth: null,
}), }),
}); });