The best in the whole network, python interface automation test - interface sign signature (combat code)


foreword

Generally, the company's external interfaces will use sign signatures to provide different apikeys for different customers, which can improve the security of interface requests and avoid random requests by modifying request parameters after being captured.

Interface sign signature

Take a login interface request as an example, the following interface captures packet information, and the signature rules of sign are as follows

The first step is to concatenate the string, first remove the sign parameter itself, and then remove the parameter p3 whose value is empty, leaving p2=v2&p1=v1&method=cancel&pn=vn, and then sort in ascending order of the parameter name characters, method=cancel&p1=v1&p2=v2&
pn =vn.
The second step is to concatenate the parameter name and value, and finally get methodcancelp1v1p2v2pnvn. The
third step is to add the verification key apikey after the above concatenated string. We assume it is abc and get the new string methodcancelp1v1p2v2pnvnabc.
Fourth step, and then convert the string to lowercase for md5 calculation, assuming that the result is abcdef, this value is the signature value of sign.

Note: Before calculating md5, please ensure that the string encoding of the interface is consistent with that of the accessing party. For example, utf-8 encoding or GBK encoding is used uniformly. If the encoding methods are inconsistent, the calculated signature will fail to verify.

POST http://127.0.0.1:8000/api/v3/login HTTP/1.1
User-Agent: Fiddler
Content-Type: application/json
Host: 127.0.0.1:8000
Content-Length: 111

{
    
    
	"username": "test",
	"password": "123456",
    "sign": "1aca01806e93bb408041965a817666af"

}

HTTP/1.1 200 OK
Date: Sat, 26 Oct 2019 03:38:31 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Content-Type: application/json
Vary: Accept, Cookie
Allow: POST, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Length: 109

{
    
    "code": 0, "msg": "login success!", "username": "test", "token": "a76ba3b8fcbdff82f6a94e5ad5bf8fb934192e5f"}

Implement sign signature

Write the pre_sign function in conftest.py to preprocess the body part of the request

import hashlib
from pytest_yaml_yoyo import my_builtins


def sign_body(body: dict) -> str:
    """对body 签名"""
    key = "12345678"      # 接口项目的开发提供
    # 去掉sign 和值为空的
    new_body = [''.join(item) for item in body.items() if item[0] != 'sign' and item[1] != '']
    # print(new_body)
    # 做排序
    new_body.sort()
    # 拼接
    # print(new_body)
    str_body = ''.join(new_body) + key
    # print(str_body)
    # md5加密

    def jiamimd5(src: str):
        """md5加密"""
        m = hashlib.md5()
        m.update(src.encode('UTF-8'))
        return m.hexdigest()

    sign = jiamimd5(str_body)
    return sign


def pre_sign(req: dict):
    print(f'请求预处理:{
      
      req}')
    sign = sign_body(req.get('json'))
    req['json']['sign'] = sign
    print(f'处理后的req数据:{
      
      req}')


my_builtins.pre_sign = pre_sign

The req parameter in the pre_sign function corresponds to the request parameter in the yaml use case, which is a dictionary type of data

test_sign_login.yml use case content

config:
  name: 登录
  hooks:
    request: ['pre_sign']

test_login:
  name: 登录
  request:
    method: POST
    url: /api/v3/login
    json:
      username: test8
      password: "123456"
  validate:
    - eq: [body.code, 0]

Run the use case

pytest test_sign_login.yml

run log

test_sign_login.yml::test_login
---------------------------------------------------- live log call -----------------------------------------------------
2023-06-08 09:45:11 [INFO]: 执行文件-> test_sign_login.yml
2023-06-08 09:45:11 [INFO]: base_url-> http://127.0.0.1:8200
2023-06-08 09:45:11 [INFO]: config variables-> {
    
    }
2023-06-08 09:45:11 [INFO]: 运行用例-> test_login
请求预处理:{
    
    'method': 'POST', 'url': '/api/v3/login', 'json': {
    
    'username': 'test8', 'password': '123456'}}
处理后的req数据:{
    
    'method': 'POST', 'url': '/api/v3/login', 'json': {
    
    'username': 'test8', 'password': '123456', 'sign': '
65faa7273d552aaedda3abdd1fe5c865'}}
2023-06-08 09:45:11 [INFO]: --------  request info ----------
2023-06-08 09:45:11 [INFO]: yml raw  -->: {
    
    'method': 'POST', 'url': '/api/v3/login', 'json': {
    
    'username': 'test8', 'passw
ord': '123456', 'sign': '65faa7273d552aaedda3abdd1fe5c865'}}
2023-06-08 09:45:11 [INFO]: method   -->: POST
2023-06-08 09:45:11 [INFO]: url      -->: /api/v3/login
2023-06-08 09:45:11 [INFO]: headers  -->: {
    
    'User-Agent': 'python-requests/2.30.0', 'Accept-Encoding': 'gzip, deflate', 'A
ccept': '*/*', 'Connection': 'keep-alive'}
2023-06-08 09:45:11 [INFO]: json     -->: {
    
    "username": "test8", "password": "123456", "sign": "65faa7273d552aaedda3abdd1f
e5c865"}
2023-06-08 09:45:11 [INFO]: ------  response info  200 OK ------
2023-06-08 09:45:11 [INFO]: 耗时     <--: 0.207054s
2023-06-08 09:45:11 [INFO]: url      <--: http://127.0.0.1:8200/api/v3/login
2023-06-08 09:45:11 [INFO]: headers  <--: {
    
    'Date': 'Thu, 08 Jun 2023 01:45:11 GMT', 'Server': 'WSGIServer/0.2 CPython/3.6
.8', 'Content-Type': 'application/json', 'Allow': 'POST, OPTIONS', 'X-Frame-Options': 'SAMEORIGIN', 'Content-Length': '11
0', 'Vary': 'Cookie'}
2023-06-08 09:45:11 [INFO]: cookies  <--: {
    
    }
2023-06-08 09:45:11 [INFO]: raw text <--: {
    
    "code": 0, "msg": "login success!", "username": "test8", "token": "045acf05c42
2ad8a40e2309ecb8de830d664e50c"}
2023-06-08 09:45:11 [INFO]: validate 校验内容-> [{
    
    'eq': ['body.code', 0]}]
2023-06-08 09:45:11 [INFO]: validate 校验结果-> eq: [0, 0]
2023-06-08 09:45:11 [INFO]: export 导出全局变量:{
    
    }
PASSED            

As can be seen from the running results, although the use case does not pass the sign parameter, the request hook in the hooks preprocesses the request parameters to realize the automatic addition of the sign parameter to the dynamic signature.

请求预处理:{
    
    'method': 'POST', 'url': '/api/v3/login', 'json': {
    
    'username': 'test8', 'password': '123456'}}
处理后的req数据:{
    
    'method': 'POST', 'url': '/api/v3/login', 'json': {
    
    'username': 'test8', 'password': '123456', 'sign': '
65faa7273d552aaedda3abdd1fe5c865'}}

The use of hooks parameters in the use case
The previous example is to put the hooks parameter in config, and the scope of action is to automatically call the preprocessing function for each request in the current yaml use case file.

config:
  name: 登录
  hooks:
    request: ['pre_sign']

If you only preprocess a single request, you can put the hooks parameter into the request parameter of the interface

config:
  name: 登录

test_login:
  name: 登录
  request:
    method: POST
    url: /api/v3/login
    json:
      username: test8
      password: "123456"
    hooks:
      request: ['pre_sign']
  validate:
    - eq: [body.code, 0]

In this way, the scope of hooks is only for a single interface request.

The following is the most complete software test engineer learning knowledge architecture system diagram in 2023 that I compiled

1. From entry to mastery of Python programming

Please add a picture description

2. Interface automation project actual combat

Please add a picture description

3. Actual Combat of Web Automation Project

Please add a picture description

4. Actual Combat of App Automation Project

Please add a picture description

5. Resume of first-tier manufacturers

Please add a picture description

6. Test and develop DevOps system

Please add a picture description

7. Commonly used automated testing tools

Please add a picture description

Eight, JMeter performance test

Please add a picture description

9. Summary (little surprise at the end)

Only by doing our best can we surpass ourselves and let our dreams soar. No matter how dense the thorns ahead are, we must bravely go through and chase the stars and seas in our hearts. Persistence, success will belong to those who dare to struggle.

Only by doing our best can we reach the other side of glory; only by persevering can we create our own miracles; as long as we have dreams in mind, every step is a brave starting point towards success. Believe in yourself and keep fighting!

Every effort is an opportunity, and every persistence is a hope. Don't be afraid to fail, success requires courage and determination. Only by constantly striving can we welcome a bright future. Believe in yourself, you can do it!

Guess you like

Origin blog.csdn.net/csdnchengxi/article/details/131557743