前端如上文《使用Java来实现JMeter自定义函数助手》一样,输入用户名、密码和Cookies保持时间,密码通过前端进行SH256散列后进行传输。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>密码进行MD5加密</title> <script type="text/javascript" src="js/sh256.js"></script> <script type="text/javascript" > function SH256Password () { document.forms["myForm"]["password"].value = SHA256(document.forms["myForm"]["password"].value); return true; } </script> </head> <form method="post" action="jsp/index.jsp" name="myForm" onsubmit="return SH256Password()"> 姓名:<input type="text" name="username" maxlength="50" value=""><br> 密码:<input type="password" name="password" maxlength="50" value=""><br> 保留时间: <select name="time"> <option value ="360">一小时</option> <option value ="8640">一天</option> <option value="259200">30天</option> <option value="1576800">半年</option> </select> <input type="submit" value="登录"> </form> <p><a href="email.html">通过Email找回密码</a></p> <p><a href="phone.html">通过短信验证码找回密码</a></p> </body> </html>
我在《使用Java来实现JMeter自定义函数助手》介绍了如何处理这种情形供JMeter使用。现在我来介绍如何用Java Request来实现。
在包api下建立IHRMLogin.java,内容如下。
package api; import utils.HTTPRequestUtils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import com.alibaba.fastjson.JSONObject; public class IHRMLogin { public JSONObject headers = new JSONObject(); public JSONObject login_data = new JSONObject(); public String url; public IHRMLogin(){ url = "http://127.0.0.1:8080/sec/46/jsp/index.jsp"; } public String loginIHRM(String username, String password,String time) { String Params = "username="+username+"&password="+getSHA256StrJava(password)+"&time="+time; return HTTPRequestUtils.sendPost(this.url, Params); } public String getSHA256StrJava(String str){ MessageDigest messageDigest; String encodeStr = ""; try { messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(str.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return encodeStr; } private static String byte2Hex(byte[] bytes){ StringBuffer stringBuffer = new StringBuffer(); String temp = null; for (int i=0;i<bytes.length;i++){ temp = Integer.toHexString(bytes[i] & 0xFF); if (temp.length()==1){ //1得到一位的进行补0操作 stringBuffer.append("0"); } stringBuffer.append(temp); } return stringBuffer.toString(); } public static void main(String[] args){ IHRMLogin ihrmLogin = new IHRMLogin(); String response = ihrmLogin.loginIHRM("cindy","123456","360"); System.out.println(response); } }
getSHA256StrJava实现SH256散列算法,在前端通过js文件来实现。
在utils包下建立HTTPRequestUtils.java。
package utils; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; import api.IHRMLogin; public class HTTPRequestUtils { /** * 向指定URL发送GET方法的请求 * * @param url * 发送请求的URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); //获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 获取所有响应头字段 Map<String, List<String>> map = conn.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输出流、输入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } public static void main(String[] args) { IHRMLogin loginApi = new IHRMLogin(); String url = "http://127.0.0.1:8080/sec/46/jsp/index.jsp"; String username = "cindy"; String password = "123456"; String time = "360"; String Params = "username="+username+"&password="+loginApi.getSHA256StrJava(password)+"&time="+time; String result = HTTPRequestUtils.sendPost(url, Params); System.out.println(result); } }
这里我采用java.net.URLConnection 来实现HTTP请求。sendGet:是发送Get请求的方法;sendPost:是发送POST请求的方法。顺便说一句,如果要在请求中加入cookies信息,可使用语句conn.setRequestProperty("Cookie", "Key=Value"); 但是我发现这个语句在Get请求中是有效的,而在POST请求中无效的。
打开WEB服务器,运行HTTPRequestUtils.java或IHRMLogin.java都应该通过。
接下来,在utils包中建立JMeter的接口Java文件:TestIHRMLogin.java。
package utils; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient; import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext; import org.apache.jmeter.samplers.SampleResult; import api.IHRMLogin; public class TestIHRMLogin implements JavaSamplerClient { private String username; private String password; private String time; public void setupTest(JavaSamplerContext javaSamplerContext) { this.username = javaSamplerContext.getParameter("username"); this.password = javaSamplerContext.getParameter("password"); this.time = javaSamplerContext.getParameter("time"); } public SampleResult runTest(JavaSamplerContext javaSamplerContext) { SampleResult result = new SampleResult(); IHRMLogin loginApi = new IHRMLogin(); // 获取当前线程编号 String threadName = Thread.currentThread().getName(); System.out.println(threadName); // 设置返回结果标签的名称 result.setSampleLabel("ihrm-" + threadName); // 在Jmeter的GUI中展示请求数据 result.setSamplerData("username="+this.username+"&password="+loginApi.getSHA256StrJava(this.password)+"&time="+this.time); // 开始事务,开始计算时间 result.sampleStart(); try { String response = loginApi.loginIHRM(this.username, this.password,this.time); // 把返回结果设置到SampleResult中 result.setResponseData(response, null); // 设置返回结果的为Text类型 result.setDataType(SampleResult.TEXT); result.setSuccessful(true); // 输出结果到控制台 } catch (Throwable e) { result.setSuccessful(false); e.printStackTrace(); } finally { // 结束事务,计算请求时间 result.sampleEnd(); } return result; } public void teardownTest(JavaSamplerContext javaSamplerContext) { } public Arguments getDefaultParameters() { Arguments arguments = new Arguments(); arguments.addArgument("username", ""); arguments.addArgument("password", ""); arguments.addArgument("time", ""); return arguments; } }
在这个Java文件中,里面包括4个方法:
- public void setupTest(JavaSamplerContext javaSamplerContext):初始化操作
- public SampleResult runTest(JavaSamplerContext javaSamplerContext):测试运行
- public void teardownTest(JavaSamplerContext javaSamplerContext) :后续处理
- public Arguments getDefaultParameters():获取参数
最后将这三个文件打成jar包(如何打jar包,请参见《使用Java来实现JMeter自定义函数助手》)一文。将打好的jar包放在%JMETER_HOME%/lib/ext/目录下。
启动JMeter,建立一个项目,首先建立线程组,在线程组下建立Java Request,在下拉列表中就可以找到utils.TestIHRMLogin了,在里面输入用户名,密码和cookies保持时间。运行就可以在“查看结果树”中看到结果了。
由于默认采用GBK,编码模式,所有出来的代码为乱码,我们需要在Java Request前加上BeanShell PostProcessor,在里面只要输入一条语句即可。
BeanShell PostProcessor
运行结果如下: