笔记-接口验签

笔记-接口验签

 

1.      接口验签

1.1.    什么是接口验签

通过HTTP post,get方式请求开放的API接口有以下几个安全上的问题需要解决:

  1. 请求来源(身份)合法性
  2. 请求参数篡改识别
  3. 请求的唯一性

为了保证数据在通信时的安全性,一般会使用参数签名的方式来进行验证。

 

1.2.    接口验签实现方法

假设需要给某 [移动端(app)] 写 [后台接口(api)]:     

客户端: 以下简称app   

后台接口:以下简称api

 

  1. 不进行验证的通信方式

api查询接口:

app访问:http://api.test.com/getproducts?para1=value1........

如上所示,没有身份验证,任何人都可以访问。

  1. MD5参数签名的通信方式

第一步,给app分配对应的key,secret;

第二步,sign签名,调用api时需要对请求参数进行签名验证,方式如下:

按照请求参数名将所有请求参数排序得到keyvaluekeyvalue….样式字符串将secret加在参数字符串的头部后进行MD5加密,加密后的字符串需大写,即得到签名sign。

新api接口代码:

http://api.test.com/getproducts?key=app_key&sign=BCC7COIWJ982398FIJ2&para1=value......

 

在这个过程中secretkey是不会在网络中传输的,所以整个过程是安全的。

  1. 另一个问题是KEY参数复用,如果key是固定的,攻击者可以很简单的复用key

常见的解决办法是timestamp+nonce

nonce是唯一的随机字符串

 

 

实现

请求接口:http://api.test.com/test?name=hello&home=world&work=java

 

客户端

 

生成当前时间戳timestamp=now和唯一随机字符串nonce=random

按照请求参数名的字母升序排列非空请求参数(包含AccessKey)

stringA="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random";

拼接密钥SecretKey

stringSignTemp="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random&SecretKey=secret";

MD5并转换为大写

sign=MD5(stringSignTemp).toUpperCase();

最终请求

http://api.test.com/test?name=hello&home=world&work=java×tamp=now&nonce=nonce&sign=sign;

 

app调用:
http://api.test.com/getproducts?key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35&timestamp=201603261407&参数1=value1&参数2=value2.......


如上,通过timestamp时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。

1.2.1.   python接口签名实现案例

#!/usr/bin/env python#coding:utf-8

import hashlib

import json

import requests

 

#测试的域名

domain= "http://******/***/vip2.ldo?"

#get 传递的非sign参数

url_params = {

    'type':'orderList',

    'userId':'198049148',

    'country':86,

    'typeGroup':'',

    'status':'',

    'rows':'20',

    'page':'1',

    'businessId':'2',

}

sign ="sign=###################"

 

#删除空值的参数,以用来签名

for key in list(url_params.keys()):

    if not url_params.get(key):

        del url_params[key]

 #按照升序排列,得到的是一个列表,列表的元素为元组      

url_params1 = sorted(url_params.items(),key=lambda d:d[0], reverse=False)

 

values =[]

for li in url_params1:

    newsmbol =('=',)

    #元组中增加一个新元素

    li = li[:1]+newsmbol+li[1:]

    #元组转化为字符串,整型不能转化,list包含数字,不能直接转化成字符串

    value = "".join('%s' %id for id in li)

values.append(value)

 

#列表复制不能用= 需要用copy 或者list[:]

values1 = values[:]

values1.append(sign)

sign1 = "&".join(values1)

#md5 调用库函数

sign2 = hashlib.md5(sign1.encode('utf-8')).hexdigest()

sign = 'sign='+sign2

values.append(sign)

para = "&".join(values)

url = domain+ para

print(url)

 

res = requests.get(url)

print('***---***---***')

print(res.content)

print('***---***---***')

print(res.headers)

print('***---***---***')

print(res.status_code)

if res.status_code == 200:

    print('请求成功')

print('***---***---***')

#json 格式打印

print(json.dumps(res.json(),indent=4))

print('***---***---***')

#两种方法

if json.loads(res.text)['msg']=='success':

    print('True')

else:

    print('error')

if res.json()['msg']=='success':

    print('True')

else:

    print('error')

 

1.3.    token

在爬取网页时经常遇到token,token实质上就是服务端给出的一个唯一性标识,其使用过程如下:

  1. 第一次访问时会给出一个标识token;
  2. 后续的每一次访问需要带上token,
  3. 服务端验证token,如果通过则可以访问,且每一次访问都会更新值。

token的主要作用是可以防止重复请求,同时有一定身份验证的作用。

当然,token具体放在cookie还是使用ajax则是工程实现的问题了。

 

1.4.    总结

身份验证的原理都是相似的,向服务器发送一个(多个)唯一性字符串,

为了解决网络传输中的监听和篡改问题,使用约定的加密算法使字符串的信息难以解读,同时防篡改。

理论上可以用用户名+密码,但为了保证安全,用户名及密码应该尽量少在网络上传输,所以实践中多在登陆后由服务端给出一个特定字符串作为标识(或作为标识的一部分)。

 

转载于:https://www.cnblogs.com/wodeboke-y/p/10386699.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值