LoadRunner報錯401(Unauthorized):
用Charles抓包對比手動操作系統和運行LoadRunner腳本后的兩次請求,發現LoadRunner 的請求頭部信息中缺少Authorization信息:
手動操作系統的 請求:
運行LoadRunner腳本后,缺少Authorization信息:
下面介紹兩種方法:
方法一:(可能只對LR11.03有效)
1、參考(https://blog.csdn.net/smooth00/article/details/65629918),發現可能是由HTTP BasicAuthenticator認證機制決定的,在腳本的web_set_user("cloudem", "cloudem","172.XX.XX.XX:8080");后面加了一句web_set_sockets_option("INITIAL_BASIC_AUTH","1"); 然后回放腳本,仍然報401錯誤(也許只對LR11.03有效)
IC認證的過程 1. 客戶端向服務器請求數據,請求的內容可能是一個網頁或者是一個其它的MIME類型,此時,假設客戶端尚未被驗證,則客戶端提供如下請求至服務器: Get /index.html HTTP/1.0 2. 服務器向客戶端發送驗證請求代碼401,服務器返回的數據大抵如下: HTTP/1.0 401 Unauthorised 3. 當符合http1.0或1.1規范的客戶端(如IE,FIREFOX)收到401返回值時,將自動彈出一個登錄窗口,要求用戶輸入用戶名和密碼。 4. 用戶輸入用戶名和密碼后,將用戶名及密碼以BASE64加密方式加密,並將密文放入前一條請求信息中,則客戶端發送的第一條請求信息則變成如下內容: Get /index.html HTTP/1.0 5. 服務器收到上述請求信息后,將Authorization字段后的用戶信息取出、解密,將解密后的用戶名及密碼與用戶數據庫進行比較驗證,如用戶名及密碼正確,服務器則根據請求,將所請求資源發送給客戶端 |
web_set_user("cloudem", "cloudem","172.XX.XX.XX:8080");也可寫成: web_set_user("cloudemr",lr_decrypt("5f92936211cde794ba0exxxx"),"172.XX.XX.XX:8080");//lr_decrypt("5f92936211cde794ba0exxxx")對密碼進行加密 |
方法二:
1、參考https://www.jianshu.com/p/ce1c18986397、
https://www.cnblogs.com/jilu1219/p/6599712.html、
http://www.cnblogs.com/preftest/archive/2011/06/12/2079178.html、
http://www.51testing.com/html/41/15103841-3707341.html
使用Base64Encoder (Base64編碼/解碼工具)制作所需的HTTP驗證基礎表頭信息,然后使用web_add_header功能添加到對應請求中(使用web_add_auto_header所有請求前面都會添加頭部信息):
主要步驟:
a:在腳本存放位置的根目錄中新建txt文件,將下列代碼拷貝到txt文件中,然后將txt文件重命名為base64.h
base64.h:
static unsigned char base64encode_lut[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";// 編譯字符表 char base64decode_lut[] = {// 解釋字符表 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,62, 0, 0, 0,63,52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25, 0, 0, 0, 0, 0, 0,26,27,28, 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, 49,50,51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; void base64encode(char *src, char *dest, int len){// 執行Base64編碼 int i=0, slen=strlen(src); for(i=0;i<slen && i<len;i+=3,src+=3) { *(dest++)=base64encode_lut[(*src&0xFC)>>0x2]; *(dest++)=base64encode_lut[(*src&0x3)<<0x4|(*(src+1)&0xF0)>>0x4]; *(dest++)=((i+1)<slen)?base64encode_lut[(*(src+1)&0xF)<<0x2|(*(src+2)&0xC0)>>0x6]:'='; *(dest++)=((i+2)<slen)?base64encode_lut[*(src+2)&0x3F]:'='; } *dest='\0'; } void base64decode(char *src, char *dest, int len){// 執行Base64解碼 int i=0, slen=strlen(src); for(i=0;i<slen&&i<len;i+=4,src+=4) { char c1=base64decode_lut[*src], c2=base64decode_lut[*(src+1)], c3=base64decode_lut[*(src+2)], c4=base64decode_lut[*(src+3)]; *(dest++)=(c1&0x3F)<<0x2|(c2&0x30)>>0x4; *(dest++)=(c3!=64)?((c2&0xF)<<0x4|(c3&0x3C)>>0x2):'\0'; *(dest++)=(c4!=64)?((c3&0x3)<<0x6|c4&0x3F):'\0'; } *dest='\0'; } int b64_encode_string( char *source, char *lrvar ){// 對字符串進行base64編譯 int dest_size; int res; char *dest; dest_size = 1 + ((strlen(source)+2)/3*4); dest = (char *)malloc(dest_size); memset(dest,0,dest_size); base64encode(source, dest, dest_size); lr_save_string( dest, lrvar ); res = strlen(dest); free(dest); return res; } int b64_decode_string( char *source, char *lrvar ){// 解碼base64字符串 int dest_size; int res; char *dest; dest_size = strlen(source); dest = (char *)malloc(dest_size); memset(dest,0,dest_size); base64decode(source, dest, dest_size); lr_save_string( dest, lrvar ); res = strlen(dest); free(dest); return res; }
b:打開腳本,在loadrunner中左側 action 模塊上,右擊,選擇“add file to script”,選中base64.h文件,導入
c:在loadrunner的globlas.h 的include files模塊 加入 #include "base64.h",如下:
// Include Files
#include "lrun.h"
#include "web_api.h"
#include "lrw_custom_body.h"
#include "base64.h" //添加內容
d:在腳本中添加如下信息:
Action()
{
//添加內容1
int res;
lr_rendezvous("login"); lr_start_transaction("login");
//錄制后自動帶入的腳本,如果沒有,則需要添加:
//web_set_user( "{Username}","{Password}", "{Domain}:{port}" );用戶名、密碼抓包能看出來,下圖可以看到,Domain服務器地址,port端口
web_set_user("cloudemr",lr_decrypt("5f92936211cde794ba0exxxx"),"172.xx.xx.xx:80");
//添加內容2
//b64_encode_string( "{Username}:{Password}","BasicAuth" );用戶名、密碼抓包能看出來,下圖可以看到,將用戶名、密碼加密后傳給BasicAuth
b64_encode_string( "cloudemr:cloudemr","BasicAuth" );
//添加內容3:添加頭部信息,放在所需要的請求上面
//Authorization:Basic XXXXXXXXXXXXXXXXXX= :XXXXXXXXXXXXXXXXXX=值取{BasicAuth}的值
web_add_header("Authorization",lr_eval_string("Basic {BasicAuth}"));
web_custom_request("token",
"URL=http://172.xx.xx.xx/app-emr-dxtest/oauth/token?verifyCode=undefined&grant_type=password&username=xxxx&password=xxxx&hospitalNo=793&orgId=undefined",
"Method=POST",
"Resource=0",
"RecContentType=application/json",
"Referer=http://172.xx.xx.xx/user/login?redirectUrl=/",
"Snapshot=t5.inf", "Mode=HTML",
"EncType=application/json;charset=UTF-8",
"Body={\"username\":\"xxxx\",\"password\":\"xxxx=\",\"hospitalNo\":793,\"remember\":true,\"grant_type\":\"password\"}",
LAST);
抓包所示Authentication用戶名、密碼信息:
e:運行后該請求不再報401錯誤
運行登錄成功后,進行別的操作仍然報錯,詳見下篇分析