Files
novalon-manage-system/novalon-manage-web/src/utils/signature.ts
T
张翔 04e385a0a2 fix: 统一签名策略,签名不包含body
根本原因:
- 前端签名生成时包含body
- 后端WebFlux验证时body为空
- 导致签名不匹配,认证失败

修复方案:
- 修改前端signature.ts,签名时不包含body
- 修改测试role-auth-manager.ts,与前端保持一致
- 与后端WebFlux实现保持一致

影响范围:
- 所有需要签名验证的API请求
- Token注入登录测试
- 用户管理相关测试
2026-04-05 07:47:28 +08:00

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)
}
}