postman项目接口文档和登录步骤原理
培训内容
实训项目:非常果岭—发现模块接口测试,单接口、流程脚本编写;
使用工具:postman
培训方式
1)postman使用说明
2)项目接口文档和登录步骤原理
一、首先了解postman使用
二、OpenSDK登录原理(APP登录),请求方式都是post
APP登录
第一步:获取oauth20_state
所需参数:response_type:code
client_id:Q_GPxHQAQZ-kYq3o1hoXtg
state:login
redirect_uri:http://www.utouu.com/
"oauth20_state": "98315c0d-85e5-4d4b-af5f-5f4eccaea21e"有失效时间,每隔10分钟重新获取
第二步:获取code
所需参数:authCode:10005,100020,100022,100021
oauth20_state:上一步获得
username:帐号13699999998
password:密码a111111
"code": "6d83408a-aaf8-4dc3-9c5f-d5baa76a6e1a",
第三步:获取access_token
所需参数:grant_type:authorization_code
client_id:Q_GPxHQAQZ-kYq3o1hoXtg
client_secret:DCXqFTbkQU2EA47yqSa3VA
code:上一步获得
redirect_uri:http://www.utouu.com/
"access_token": "39e6c176-bdb9-48f0-b023-fccf2734ed6a"
第四步:获取openid和appid
"openid": "UVoUy6IyhKvuLtDPvP_qAnouExXs",
"client_id": "Q_GPxHQAQZ-kYq3o1hoXtg",
所需参数:access_token:上一步获得
第五步登录:以非常果岭为例登录接口,获取userid
app.utgreen.test.utsoft.cn/oauth-authorize/login?openId=UVoUy6IyhKvuLtDPvP_qAnouExXs&accessToken=d4771e6f-c862-499d-ae50-d044b84ca654&udid=11&appid=Q_GPxHQAQZ-kYq3o1hoXtg
"userId": "b5a5aba1-30aa-45df-b474-b84731860047",
---------------------------------------------------------------------------------------------------------------------------
test中的打印语句:
tests["Body matches string"] =responseBody.has("string_you_want_to_search");
tests[timestamp] = timestamp;
帐号密码:
18140048905,a111111
18140048906,a111111
18140048907,a111111
18140048908,a111111
18140048909,a111111
18140048900,a111111
设置一个环境变量由一个时间函数返回他的值
postman.setEnvironmentVariable('timestampHeader',new Date());
遗留
2.APP接口的访问
采用OpenSDK登录的APP接口,大部分除了接口文档需要的参数外,还需要如下参数:
utouu-open-client-ticket:用户登录的ticket
utouu-open-client-appid:在登录过程中已经获取到
utouu-open-client-sign:获取的sign
utouu-open-client-time:登录的时间戳
sign校验原理
1.获取得到时间戳
var timestamp = (new Date()).valueOf();
postman.setEnvironmentVariable('time',timestamp);
2.取得传入参数并对key升序排序,对value进行字符串拼接
postman:如何将A请求中responseBody中的参数值传入到下一个请求B的request中作为参数发送请求
https://my.oschina.net/1157600353/blog/814237
3.对时间戳采用MD5加密,加密长度16位
1 // 对时间戳加密 2 // 方法一:MD5函数加密 3 String.prototype.MD5 = function (bit) 4 { 5 var sMessage = this; 6 function RotateLeft(lValue, iShiftBits) { return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); } 7 function AddUnsigned(lX,lY) 8 { 9 var lX4,lY4,lX8,lY8,lResult; 10 lX8 = (lX & 0x80000000); 11 lY8 = (lY & 0x80000000); 12 lX4 = (lX & 0x40000000); 13 lY4 = (lY & 0x40000000); 14 lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF); 15 if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8); 16 if (lX4 | lY4) 17 { 18 if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); 19 else return (lResult ^ 0x40000000 ^ lX8 ^ lY8); 20 } else return (lResult ^ lX8 ^ lY8); 21 } 22 function F(x,y,z) { return (x & y) | ((~x) & z); } 23 function G(x,y,z) { return (x & z) | (y & (~z)); } 24 function H(x,y,z) { return (x ^ y ^ z); } 25 function I(x,y,z) { return (y ^ (x | (~z))); } 26 function FF(a,b,c,d,x,s,ac) 27 { 28 a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); 29 return AddUnsigned(RotateLeft(a, s), b); 30 } 31 function GG(a,b,c,d,x,s,ac) 32 { 33 a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); 34 return AddUnsigned(RotateLeft(a, s), b); 35 } 36 function HH(a,b,c,d,x,s,ac) 37 { 38 a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); 39 return AddUnsigned(RotateLeft(a, s), b); 40 } 41 function II(a,b,c,d,x,s,ac) 42 { 43 a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); 44 return AddUnsigned(RotateLeft(a, s), b); 45 } 46 function ConvertToWordArray(sMessage) 47 { 48 var lWordCount; 49 var lMessageLength = sMessage.length; 50 var lNumberOfWords_temp1=lMessageLength + 8; 51 var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64; 52 var lNumberOfWords = (lNumberOfWords_temp2+1)*16; 53 var lWordArray=Array(lNumberOfWords-1); 54 var lBytePosition = 0; 55 var lByteCount = 0; 56 while ( lByteCount < lMessageLength ) 57 { 58 lWordCount = (lByteCount-(lByteCount % 4))/4; 59 lBytePosition = (lByteCount % 4)*8; 60 lWordArray[lWordCount] = (lWordArray[lWordCount] | (sMessage.charCodeAt(lByteCount)<<lBytePosition)); 61 lByteCount++; 62 } 63 lWordCount = (lByteCount-(lByteCount % 4))/4; 64 lBytePosition = (lByteCount % 4)*8; 65 lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition); 66 lWordArray[lNumberOfWords-2] = lMessageLength<<3; 67 lWordArray[lNumberOfWords-1] = lMessageLength>>>29; 68 return lWordArray; 69 } 70 function WordToHex(lValue) 71 { 72 var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; 73 for (lCount = 0;lCount<=3;lCount++) 74 { 75 lByte = (lValue>>>(lCount*8)) & 255; 76 WordToHexValue_temp = "0" + lByte.toString(16); 77 WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2); 78 } 79 return WordToHexValue; 80 } 81 var x=Array(); 82 var k,AA,BB,CC,DD,a,b,c,d 83 var S11=7, S12=12, S13=17, S14=22; 84 var S21=5, S22=9 , S23=14, S24=20; 85 var S31=4, S32=11, S33=16, S34=23; 86 var S41=6, S42=10, S43=15, S44=21; 87 // Steps 1 and 2. Append padding bits and length and convert to words 88 x = ConvertToWordArray(sMessage); 89 // Step 3. Initialise 90 a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; 91 // Step 4. Process the message in 16-word blocks 92 for (k=0;k<x.length;k+=16) 93 { 94 AA=a; BB=b; CC=c; DD=d; 95 a=FF(a,b,c,d,x[k+0], S11,0xD76AA478); 96 d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756); 97 c=FF(c,d,a,b,x[k+2], S13,0x242070DB); 98 b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE); 99 a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF); 100 d=FF(d,a,b,c,x[k+5], S12,0x4787C62A); 101 c=FF(c,d,a,b,x[k+6], S13,0xA8304613); 102 b=FF(b,c,d,a,x[k+7], S14,0xFD469501); 103 a=FF(a,b,c,d,x[k+8], S11,0x698098D8); 104 d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF); 105 c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1); 106 b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE); 107 a=FF(a,b,c,d,x[k+12],S11,0x6B901122); 108 d=FF(d,a,b,c,x[k+13],S12,0xFD987193); 109 c=FF(c,d,a,b,x[k+14],S13,0xA679438E); 110 b=FF(b,c,d,a,x[k+15],S14,0x49B40821); 111 a=GG(a,b,c,d,x[k+1], S21,0xF61E2562); 112 d=GG(d,a,b,c,x[k+6], S22,0xC040B340); 113 c=GG(c,d,a,b,x[k+11],S23,0x265E5A51); 114 b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA); 115 a=GG(a,b,c,d,x[k+5], S21,0xD62F105D); 116 d=GG(d,a,b,c,x[k+10],S22,0x2441453); 117 c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681); 118 b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8); 119 a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6); 120 d=GG(d,a,b,c,x[k+14],S22,0xC33707D6); 121 c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87); 122 b=GG(b,c,d,a,x[k+8], S24,0x455A14ED); 123 a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905); 124 d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8); 125 c=GG(c,d,a,b,x[k+7], S23,0x676F02D9); 126 b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A); 127 a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942); 128 d=HH(d,a,b,c,x[k+8], S32,0x8771F681); 129 c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122); 130 b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C); 131 a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44); 132 d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9); 133 c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60); 134 b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70); 135 a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6); 136 d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA); 137 c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085); 138 b=HH(b,c,d,a,x[k+6], S34,0x4881D05); 139 a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039); 140 d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5); 141 c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8); 142 b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665); 143 a=II(a,b,c,d,x[k+0], S41,0xF4292244); 144 d=II(d,a,b,c,x[k+7], S42,0x432AFF97); 145 c=II(c,d,a,b,x[k+14],S43,0xAB9423A7); 146 b=II(b,c,d,a,x[k+5], S44,0xFC93A039); 147 a=II(a,b,c,d,x[k+12],S41,0x655B59C3); 148 d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92); 149 c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D); 150 b=II(b,c,d,a,x[k+1], S44,0x85845DD1); 151 a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F); 152 d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0); 153 c=II(c,d,a,b,x[k+6], S43,0xA3014314); 154 b=II(b,c,d,a,x[k+13],S44,0x4E0811A1); 155 a=II(a,b,c,d,x[k+4], S41,0xF7537E82); 156 d=II(d,a,b,c,x[k+11],S42,0xBD3AF235); 157 c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB); 158 b=II(b,c,d,a,x[k+9], S44,0xEB86D391); 159 a=AddUnsigned(a,AA); b=AddUnsigned(b,BB); c=AddUnsigned(c,CC); d=AddUnsigned(d,DD); 160 } 161 if(bit==32) 162 { 163 return WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d); 164 } 165 else 166 { 167 return WordToHex(b)+WordToHex(c); 168 } 169 } 170 // 将时间戳转换为字符串格式 171 var str1 = timestamp.toString(); // 转换格式 172 var md16 = str1.MD5(); // 调用加密方法,默认为16位加密 173 postman.setEnvironmentVariable('timestampMD5',md16); 174 175 // 方法二:使用CryptoJS库所带的MD5加密 176 var str2 = timestamp.toString();// 转换格式 177 var md161 = CryptoJS.MD5(str2).toString(); // 加密后转换格式 178 var md162 = md161.substr(8,16); // 获取中间16位MD5码 179 postman.setEnvironmentVariable('2',md162);
4.将value与加密后的时间戳拼接,注意:拼接时加冒号分隔
var long = "e99b4dbd-60a8-4738-b2a0-9e0f97c1e9e9" + ":" + md16;
postman.setEnvironmentVariable('valueAndMD5',long);
对拼接后的值进行Base64加密
// 方法一:使用函数对拼接后的字符进行Base64加密 function Base64() { // private property _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; // public method for encoding this.encode = function (input) { var output = ""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; input = _utf8_encode(input); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4); } return output; } // public method for decoding this.decode = function (input) { var output = ""; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); while (i < input.length) { enc1 = _keyStr.indexOf(input.charAt(i++)); enc2 = _keyStr.indexOf(input.charAt(i++)); enc3 = _keyStr.indexOf(input.charAt(i++)); enc4 = _keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } } output = _utf8_decode(output); return output; } // private method for UTF-8 encoding _utf8_encode = function (string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } // private method for UTF-8 decoding _utf8_decode = function (utftext) { var string = ""; var i = 0; var c = c1 = c2 = 0; while ( i < utftext.length ) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; } else if((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i+1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = utftext.charCodeAt(i+1); c3 = utftext.charCodeAt(i+2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return string; } } var b64 = new Base64(); // 创建一个对象 var sign = b64.encode(long); // 调用函数中的encode方法进行64位编码获取到对应的sign postman.setEnvironmentVariable('signBase64',sign); // 方法二:使用CryptoJS库对字符串进行Base64转码,加密就是转码 // 拼接后的long是utf-8格式的字符串 var words = CryptoJS.enc.Utf8.parse(long); // 转换成WordArray object postman.setEnvironmentVariable('1',words); var sign1 = CryptoJS.enc.Base64.stringify(words); // 将数组对象进行转为Base64格式字符串 postman.setEnvironmentVariable('2',sign1);
5.得到sign
Henry