04e385a0a2
根本原因: - 前端签名生成时包含body - 后端WebFlux验证时body为空 - 导致签名不匹配,认证失败 修复方案: - 修改前端signature.ts,签名时不包含body - 修改测试role-auth-manager.ts,与前端保持一致 - 与后端WebFlux实现保持一致 影响范围: - 所有需要签名验证的API请求 - Token注入登录测试 - 用户管理相关测试
97 lines
2.0 KiB
TypeScript
97 lines
2.0 KiB
TypeScript
import CryptoJS from 'crypto-js'
|
|
|
|
const SIGNATURE_SECRET = 'NovalonManageSystemSecretKey2026'
|
|
|
|
export interface SignatureHeaders {
|
|
'X-Signature': string
|
|
'X-Timestamp': string
|
|
'X-Nonce': string
|
|
}
|
|
|
|
export function generateSignature(
|
|
method: string,
|
|
path: string,
|
|
query: string = '',
|
|
body: string = '',
|
|
timestamp: number,
|
|
nonce: string
|
|
): string {
|
|
const stringToSign = buildStringToSign(method, path, query, '', timestamp, nonce)
|
|
|
|
const signature = CryptoJS.HmacSHA256(stringToSign, SIGNATURE_SECRET)
|
|
const signatureBase64 = CryptoJS.enc.Base64.stringify(signature)
|
|
|
|
return signatureBase64
|
|
}
|
|
|
|
export function generateSignatureHeaders(
|
|
method: string,
|
|
url: string,
|
|
body?: any
|
|
): SignatureHeaders {
|
|
const timestamp = Date.now()
|
|
const nonce = generateNonce()
|
|
|
|
const { path, query } = parseUrl(url)
|
|
const bodyString = body ? JSON.stringify(body) : ''
|
|
|
|
const signature = generateSignature(
|
|
method.toUpperCase(),
|
|
path,
|
|
query || '',
|
|
bodyString,
|
|
timestamp,
|
|
nonce
|
|
)
|
|
|
|
return {
|
|
'X-Signature': signature,
|
|
'X-Timestamp': timestamp.toString(),
|
|
'X-Nonce': nonce
|
|
}
|
|
}
|
|
|
|
function buildStringToSign(
|
|
method: string,
|
|
path: string,
|
|
query: string,
|
|
body: string,
|
|
timestamp: number,
|
|
nonce: string
|
|
): string {
|
|
return [
|
|
method,
|
|
path,
|
|
query || '',
|
|
body || '',
|
|
timestamp.toString(),
|
|
nonce
|
|
].join('\n')
|
|
}
|
|
|
|
function generateNonce(): string {
|
|
const timestamp = Date.now().toString(36)
|
|
const randomPart = Math.random().toString(36).substring(2, 15)
|
|
return `${timestamp}-${randomPart}`
|
|
}
|
|
|
|
function parseUrl(url: string): { path: string; query: string } {
|
|
if (url.startsWith('http://') || url.startsWith('https://')) {
|
|
const urlObj = new URL(url)
|
|
return {
|
|
path: urlObj.pathname,
|
|
query: urlObj.search.substring(1)
|
|
}
|
|
}
|
|
|
|
const queryIndex = url.indexOf('?')
|
|
if (queryIndex === -1) {
|
|
return { path: url, query: '' }
|
|
}
|
|
|
|
return {
|
|
path: url.substring(0, queryIndex),
|
|
query: url.substring(queryIndex + 1)
|
|
}
|
|
}
|