Jmeter 440错误代码.我该如何解决该错误? [英] Jmeter 440 error code. How can I resolve this error?
问题描述
我正在用Genexus制作的Web登录脚本中使用Jmeter和Blazemeter.我遇到的问题在POST中.
每当我尝试进行POST http请求时,Jmeter都会抛出下一件事:
如您所见,在响应正文中,我有一个440 http错误代码.这是登录超时,表示客户端会话已过期,必须再次登录.我曾经有一个403错误代码,但是现在,经过一些安排,我有了440.对于如何解决这个问题,您有任何建议吗?
首先,我不是Genexus的专家.我所有的发现都是从黑匣子的角度来看的.
Genexus Security
我发现Genexus至少需要两件事才能在Web应用程序上进行身份验证(我仅测试了Java和.Net生成的应用程序).
-
GXState
参数.此参数是在发布请求后发送的,据我了解,该参数用作同步器令牌模式",请参见已创建变量的名称:
GXState
正则表达式:
name ="GXState";value ='(.*?)'
模板:
$ 1 $
匹配编号:
1
默认值:
NOT_FOUND
-
GXState
是一个JSON对象,从中我们可以提取GX_AJAX_KEY
来加密gxajaxEvt
字符串.请注意,在这种情况下,我发现GX_AJAX_KEY
是用于加密的密钥,但也可以应用其他一些密钥.我们可以使用Browser Web Console对此进行调试:
gx.sec.encrypt("gxajaxEvt")
我们将看到以下内容:" 8722e2ea52fd44f599d35d1534485d8e206d507a46070a816ca7fcdbe812b0ad"
我们发现,所有客户端加密代码都在 gxgral.js
文件中.Genexus使用
要在JMeter脚本中模拟此客户端行为,我们可以使用"JSR 233采样器".获得Rijndael结果的一种方法是使用Bouncy Castle库.我们需要添加此jar
- 使用这些变量,我们可以成功发送下一个请求:
我们可以在此处找到该示例JMeter脚本.
.有关复杂脚本,请参考本指南(需要GXTest)
如果我们在JMeter中收到此异常( java.util.zip.ZipException:不是GZIP格式
),请参考此 解决方案
First, I'm not an expert on Genexus. All my findings are from a black-box point of view.
Genexus Security
I found that Genexus requires at least two things to authenticate on Web Application (I tested only Java and .Net generated apps).
The
GXState
parameter. This param is sent in post request, and from my understanding works as "Synchronizer token pattern", see more info on Cross-site request forgery. We need to send this param on every post request.The
gxajaxEvt
parameter. This is very specific to Genexus Apps. In the documentation mentions this parameter is send encrypted in the URL, and this behavior is managed by the "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 Script
So, to get the
GXState
, we can use theRegular Expression Extractor
:Name of created variable:
GXState
Regular expression:
name="GXState" value='(.*?)'
Template:
$1$
Match No.:
1
Default Value:
NOT_FOUND
The
GXState
is a JSON, object, from it we can extract theGX_AJAX_KEY
to encryptgxajaxEvt
string. Note that, I found theGX_AJAX_KEY
is the key used to encrypt in this case, but some others could apply. We can debug this using Browser Web Console, with this:
gx.sec.encrypt("gxajaxEvt")
We'll see something like this:
"8722e2ea52fd44f599d35d1534485d8e206d507a46070a816ca7fcdbe812b0ad"
As we can found, all the client encryption code is in the gxgral.js
file. Genexus uses the Rijndael algortihm (Sub set of AES) with block size of 128 bits.
To emulate this client behavior in the JMeter Script we can use the "JSR 233 sampler". A way to get the Rijndael results is use the Bouncy Castle library. We need to add this jar (bouncycastle:bcprov-jdk15to18:1.68) to the JMeter's lib folder to use it.
Our code script will be something like this (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)
The script work like this:
- First, We get the previos
GXState
variable extracted. - Second, Using JSON Path (Already available in JMeter 5.4) extract the
GX_AJAX_KEY
property. - Third, We apply the Rijndael algorithm over the
gxajaxEvt
using theGX_AJAX_KEY
as a key. - We also create the
gx-no-cache
to handle the cache.
- With these variables we can send the next request successfully:
We can found this sample JMeter script available here.
For complex scripts, please refer to this guide (Requires GXTest)
In case we get this exception in JMeter ( java.util.zip.ZipException: Not in GZIP format
) please refer this answer too.
这篇关于Jmeter 440错误代码.我该如何解决该错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!