培训内容
实训项目:非常果岭—发现模块接口测试,单接口、流程脚本编写;
使用工具: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

postman项目接口文档和登录步骤原理的更多相关文章

  1. [Django REST framework - 自动生成接口文档、分页]

    [Django REST framework - 自动生成接口文档.分页] 自动生成接口文档 # 后端人员写好接口,编写接口文档,给前端人员看,前端人员依照接口文档开发 # 公司里主流 -后端,使用w ...

  2. 推荐一款接口文档在线管理系统-MinDoc

    项目简介 MinDoc 是一款针对IT团队开发的简单好用的文档管理系统. MinDoc 的前身是 SmartWiki 文档系统.SmartWiki 是基于 PHP 框架 laravel 开发的一款文档 ...

  3. Spring Boot 系列(七)Swagger2-生成RESTful接口文档

    Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集成到服 ...

  4. 《MinDoc 接口文档在线管理系统》

    项目简介 MinDoc 是一款针对IT团队开发的简单好用的文档管理系统. MinDoc 的前身是 SmartWiki 文档系统.SmartWiki 是基于 PHP 框架 laravel 开发的一款文档 ...

  5. SpringBoot开发mockserver及生成swagger接口文档

    通过springboot开发mock server,包含get及post接口,用于练习接口自动化及jmeter很方便 当然,也为后面jenkins持续集成做基础(开发push代码后  → jenkin ...

  6. 如何使用Swagger-UI在线生成漂亮的接口文档

    一.简单介绍 Swagger是一个实现了OpenAPI(OpenAPI Specification)规范的工具集.OpenAPI是Linux基金会的一个项目,试图通过定义一种用来描述API格式或API ...

  7. spring-boot-route(五)整合Swagger生成接口文档

    目前,大多数公司都采用了前后端分离的开发模式,为了解决前后端人员的沟通问题,后端人员在开发接口的时候会选择使用swagger2来生成对应的接口文档,swagger2提供了强大的页面调试功能,这样可以有 ...

  8. 接口文档管理工具-Postman、Swagger、RAP(转载)

    接口文档管理工具-Postman.Swagger.RAP 转自:http://www.51testing.com/html/10/n-3715910.html 在项目开发测试中,接口文档是贯穿始终的. ...

  9. springboot项目利用Swagger2生成在线接口文档

    Swagger简介. Swagger2是一款restful接口文档在线生成和在线调试工具.很多项目团队利用Swagger自动生成接口文档,保证接口文档和代码同步更新.在线调试.简单地说,你可以利用这个 ...

随机推荐

  1. Microsoft HoloLens 开发(3): 全息图交互方式 - Gaze

    Gaze(凝视) 是 HoloLens 交互输入的第一种形式,告诉你 用户 在世界上的位置,并让你确定他们的意图. 1.Gaze的用途 作为一个 Mixed Reality 开发者,Gaze 可以做很 ...

  2. linux(CentOS7) 之 MySQL 5.7.30 下载及安装

    一.下载 1.百度搜索mysql,进入官网(或直接进入官网https://www.mysql.com) 2.选择 downloads 3.翻到最下面,选择MySQL Community (GPL) D ...

  3. mysql数据库忘记root密码怎么办?

    mysql数据库忘记root密码怎么破解和修改 1.停止数据库的运行 [root@localhost ~]# /etc/init.d/mysqld stop 或者[root@localhost ~]# ...

  4. 《挑战程序设计竞赛》1.6.2-POJ的题目Ants

    #include <stdio.h> #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < ...

  5. Zookeeper绍二(分布式锁介)

    一.为什么会有分布式锁? 在多线程环境下,由于上下文的切换,数据可能出现不一致的情况或者数据被污染,我们需要保证数据安全,所以想到了加锁. 所谓的加锁机制呢,就是当一个线程访问该类的某个数据时,进行保 ...

  6. Android官方文档翻译 十七 4.1Starting an Activity

    Starting an Activity 开启一个Activity This lesson teaches you to 这节课教给你 Understand the Lifecycle Callbac ...

  7. Vue 动态设置图片路径

      大多数情况vue项目中组件是需要相互引用的,父组件引用子组件,子组件引用父组件,已达到组件重用的目的   本次记录的是父组件引用子组件,img标签定义在多个子组件中,不同或相同的父组件引用同一个子 ...

  8. 《剑指offer》面试题21. 调整数组顺序使奇数位于偶数前面

    问题描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分. 示例: 输入:nums = [1,2,3,4] 输出:[1,3,2,4] ...

  9. JUC之阻塞队列(BlockingQueue)基础

    阻塞队列 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作支持阻塞的插入和移除方法. 阻塞队列常用于生产者和消费者的场景: 当队列为空的,从队列中获取元素的操作将会 ...

  10. C++11多线程之future(一)

    // ConsoleApplication5.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #include<random> #in ...