Jmeter 440错误代码。如何解决此错误?

时间:2019-11-27 15:11:45

标签: jmeter genexus

我正在用Genexus制作的Web登录脚本中使用Jmeter和Blazemeter。 我遇到的问题在POST中。

每当我尝试进行POST http请愿时,Jmeter都会抛出下一件事: enter image description here

如您所见,在响应正文中,我有一个440 http错误代码。这是登录超时,表示客户端会话已过期,必须再次登录。我曾经有一个403错误代码,但现在,经过一些安排,我有了440。对于如何解决这个问题,您有任何建议吗?

2 个答案:

答案 0 :(得分:1)

任何HTTP Status 4xx客户端错误,以表示您发送的请求不正确。

如果自定义440 http status code表示“会话已过期”,我的期望是您的请求参数或headers

中有记录的硬编码会话ID。

一旦找到它,您应该仔细检查以前的响应并查找似乎是会话ID的内容-extract it using a suitable JMeter's Post-Processor,然后用适当的JMeter变量替换硬编码的会话ID。该过程称为 correlation

答案 1 :(得分:1)

首先,我不是 Genexus 的专家。我所有的发现都是从黑匣子的角度来看的。

Genexus 安全

我发现 Genexus 至少需要两件事才能在 Web 应用程序上进行身份验证(我只测试了 Java 和 .Net 生成的应用程序)。

  1. GXState 参数。这个参数是在 post 请求中发送的,根据我的理解,它是“同步器令牌模式”,请参阅有关 Cross-site request forgery 的更多信息。我们需要在每次发布请求时发送此参数。

  2. gxajaxEvt 参数。这是 Genexus Apps 特有的。在 documentation 中提到此参数在 URL 中加密发送,并且此行为由“Javascript debug mode property”管理:

# Javascript Debug Mode: Yes
http://{server}:{port}/{webappname}/servlet/com.{kbname}.{objectname}?gxfullajaxEvt,gx-no-cache=1442811265833
# Javascript Debug Mode: No (default value)
http://{server}:{port}/{webappname}/servlet/com.{kbname}.{objectname}?64df96a2d9b8480aed416e470dae529e,gx-no-cache=1442811265833

JMeter 脚本

  1. 因此,要获得 GXState,我们可以使用 Regular Expression ExtractorRegular Expression Extractor

    创建的变量名称:GXState

    正则表达式:name="GXState" value='(.*?)'

    模板:$1$

    比赛编号:1

    默认值:NOT_FOUND

  2. GXState 是一个 JSON 对象,我们可以从中提取 GX_AJAX_KEY 来加密 gxajaxEvt 字符串。请注意,我发现 GX_AJAX_KEY 是在这种情况下用于加密的密钥,但其他一些也可以应用。我们可以使用浏览器 Web 控制台对此进行调试:

gx.sec.encrypt("gxajaxEvt")

我们会看到这样的事情: "8722e2ea52fd44f599d35d1534485d8e206d507a46070a816ca7fcdbe812b0ad"

我们可以发现,所有客户端加密代码都在 gxgral.js 文件中。 Genexus 使用 Rijndael 算法(AES 的子集),块大小为 128 位。

Browser Web Console

要在 JMeter 脚本中模拟此客户端行为,我们可以使用“JSR 233 采样器”。获得 Rijndael 结果的一种方法是使用 Bouncy Castle 库。我们需要将此 jar (bouncycastle:bcprov-jdk15to18:1.68) 添加到 JMeter 的 lib 文件夹中才能使用它。

我们的代码脚本将是这样的(Language Groovy 3.0.5/Groovy Scripting Engine 2.0):

import com.jayway.jsonpath.JsonPath
import java.nio.charset.StandardCharsets
import java.util.Arrays
import org.bouncycastle.crypto.BufferedBlockCipher
import org.bouncycastle.crypto.InvalidCipherTextException
import org.bouncycastle.crypto.engines.RijndaelEngine
import org.bouncycastle.crypto.params.KeyParameter
import org.bouncycastle.util.encoders.Hex
import org.apache.jmeter.threads.JMeterContextService
import org.apache.jmeter.threads.JMeterContext
import org.apache.jmeter.threads.JMeterVariables

String gxState = vars.get('GXState')
String gxAjaxKey = JsonPath.read(gxState,'$.GX_AJAX_KEY')
byte[] input = Arrays.copyOf('gxajaxEvt'.getBytes(StandardCharsets.UTF_8), 16)
RijndaelEngine engine = new RijndaelEngine(128)
KeyParameter key = new KeyParameter(Hex.decode(gxAjaxKey))
BufferedBlockCipher cipher = new BufferedBlockCipher(engine)
cipher.init(true, key)
byte[] out = new byte[16]
int length = cipher.processBytes(input, 0, 16, out, 0)
cipher.doFinal(out, length)
String encryptedOutput= Hex.toHexString(out)
log.info 'gx.sec.encrypt("gxajaxEvt")='+encryptedOutput
String gxNoCache = String.valueOf(System.currentTimeMillis())
log.info 'gx-no-cache='+gxNoCache
vars.put('gxajaxEvt', encryptedOutput)
vars.put('gxNoCache', gxNoCache)

脚本是这样工作的:

  • 首先,我们提取了之前的 GXState 变量。
  • 其次,使用 JSON 路径(已经 available in JMeter 5.4.1)提取 GX_AJAX_KEY 属性。
  • 第三,我们在 gxajaxEvt 上应用 Rijndael 算法,使用 GX_AJAX_KEY 作为键。
  • 我们还创建了 gx-no-cache 来处理缓存。

JSR233 Sampler

  1. 使用这些变量,我们可以成功发送下一个请求: Next HTTP Request

我们可以找到此示例 JMeter 脚本可用 here

复杂脚本请参考this guide(需要GXTest)

如果我们在 JMeter (java.util.zip.ZipException: Not in GZIP format) 中遇到此异常,请也参考此 answer