You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JMeter中修改Password_Digest并为SOAP请求添加WSS与WS-Addressing?

我帮你梳理下SOAP请求添加WSS UsernameToken(带Password Digest)和WS-Addressing的正确姿势,还有JMeter里的具体操作步骤——

1. 先搞对WSS UsernameToken的Password_Digest生成逻辑

你给出的公式是对的,但要注意几个容易踩坑的细节:
Password_Digest = Base64 ( SHA-1 ( nonce + created + Base64 ( SHA-1 ( password ) ) ) )

  • nonce:必须是随机唯一的二进制值(比如16字节随机串),每次请求都要换,而且要同时在UsernameToken里传递它的Base64编码值
  • created:必须是UTC时区的ISO 8601格式时间戳,比如2024-05-20T14:23:00Z,要和nonce一一对应
  • 计算步骤拆解(别搞混字节和字符串):
    1. 先对原始密码做SHA-1哈希,再转Base64,得到SHA1_PWD_BASE64
    2. 生成16字节随机nonce,转Base64得到NONCE_BASE64(用于XML里的Nonce字段),同时保留原始二进制nonce用于后续拼接
    3. 获取当前UTC时间的ISO 8601字符串CREATED
    4. 把原始二进制nonce + CREATED的UTF-8字节 + SHA1_PWD_BASE64的UTF-8字节拼接在一起
    5. 对拼接后的字节做SHA-1哈希,再转Base64就是最终的Password_Digest

示例WSS UsernameToken XML结构

<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
  <wsse:UsernameToken>
    <wsse:Username>your_username</wsse:Username>
    <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">GENERATED_DIGEST</wsse:Password>
    <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NONCE_BASE64</wsse:Nonce>
    <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2024-05-20T14:23:00Z</wsu:Created>
  </wsse:UsernameToken>
</wsse:Security>
2. 给SOAP请求添加WS-Addressing(WSA)

WS-Addressing需要在SOAP Header里添加几个核心元素,注意命名空间要和服务端要求一致(通常是http://www.w3.org/2005/08/addressing,少数用旧版2004的):

<soapenv:Header>
  <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">https://your-soap-endpoint-url</wsa:To>
  <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://your-target-namespace/your-operation-name</wsa:Action>
  <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">urn:uuid:3e4a7f9b-1c2d-5e6f-7g8h-9i0j1k2l3m4n</wsa:MessageID>
  <wsa:ReplyTo xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
  </wsa:ReplyTo>
</soapenv:Header>
  • wsa:Action必须严格匹配你调用的SOAP操作的命名空间+操作名,比如服务端定义的http://example.com/orders/CreateOrder
  • wsa:MessageID每次请求要生成新的UUID,避免重复
3. JMeter里的具体配置步骤

3.1 用JSR223 PreProcessor计算动态参数

JMeter自带函数搞不定这么复杂的哈希逻辑,直接用Groovy脚本(性能最优)生成所有动态变量:

  1. 在你的SOAP请求Sampler下添加JSR223 PreProcessor
  2. 语言选择Groovy,粘贴以下脚本(替换username和password为你的实际值):
import java.security.MessageDigest
import java.util.Base64
import java.util.UUID
import java.text.SimpleDateFormat
import java.util.TimeZone

// 配置你的账号密码
def username = "your_real_username"
def password = "your_real_password"

// 步骤1:计算密码的SHA1->Base64
MessageDigest sha1 = MessageDigest.getInstance("SHA-1")
byte[] pwdSha1Bytes = sha1.digest(password.getBytes("UTF-8"))
def pwdSha1Base64 = Base64.getEncoder().encodeToString(pwdSha1Bytes)

// 步骤2:生成随机nonce
byte[] nonceBytes = new byte[16]
new Random().nextBytes(nonceBytes)
def nonceBase64 = Base64.getEncoder().encodeToString(nonceBytes)

// 步骤3:生成UTC时间戳
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
sdf.setTimeZone(TimeZone.getTimeZone("UTC"))
def created = sdf.format(new Date())

// 步骤4:拼接字节并计算最终Digest
byte[] createdBytes = created.getBytes("UTF-8")
byte[] pwdSha1Base64Bytes = pwdSha1Base64.getBytes("UTF-8")
byte[] combinedBytes = new byte[nonceBytes.length + createdBytes.length + pwdSha1Base64Bytes.length]
System.arraycopy(nonceBytes, 0, combinedBytes, 0, nonceBytes.length)
System.arraycopy(createdBytes, 0, combinedBytes, nonceBytes.length, createdBytes.length)
System.arraycopy(pwdSha1Base64Bytes, 0, combinedBytes, nonceBytes.length + createdBytes.length, pwdSha1Base64Bytes.length)
byte[] digestBytes = sha1.digest(combinedBytes)
def passwordDigest = Base64.getEncoder().encodeToString(digestBytes)

// 把变量存入JMeter上下文,供SOAP请求使用
vars.put("username", username)
vars.put("passwordDigest", passwordDigest)
vars.put("nonceBase64", nonceBase64)
vars.put("created", created)
vars.put("messageId", "urn:uuid:" + UUID.randomUUID())

3.2 修改SOAP请求的XML模板

把SOAP请求的Body里的静态值替换成JMeter变量,示例如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ord="http://example.com/orders">
   <soapenv:Header>
      <!-- WS-Addressing部分 -->
      <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">https://your-soap-endpoint.com/orders</wsa:To>
      <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://example.com/orders/CreateOrder</wsa:Action>
      <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">${messageId}</wsa:MessageID>
      <wsa:ReplyTo xmlns:wsa="http://www.w3.org/2005/08/addressing">
         <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
      </wsa:ReplyTo>
      <!-- WSS UsernameToken部分 -->
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:UsernameToken>
            <wsse:Username>${username}</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">${passwordDigest}</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">${nonceBase64}</wsse:Nonce>
            <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">${created}</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <!-- 你的SOAP请求体 -->
      <ord:CreateOrder>
         <ord:OrderID>12345</ord:OrderID>
         <ord:Amount>99.99</ord:Amount>
      </ord:CreateOrder>
   </soapenv:Body>
</soapenv:Envelope>

3.3 调试和验证

  • 添加View Results Tree sampler,查看实际发送的XML是否正确替换了所有变量
  • 如果还是失败,重点检查:
    • 是否用了原始二进制nonce参与拼接(别误用Base64后的字符串)
    • created时间是否是UTC时区,格式是否正确
    • WS-Addressing的命名空间是否和服务端要求一致
    • 有些服务端可能对Password_Digest的拼接顺序有调整,比如把created放在nonce前面,可以尝试修改脚本里的拼接顺序

内容的提问来源于stack exchange,提问作者Pixi Dixi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:12:39