自行实现 API 请求认证

13 篇文章 0 订阅

在 HTTP 的 API 请求,作为后台服务需要知道请求者是谁,当然对 Django 项目有好多现成的解决方案 DRF token 和 JWT token 等,现在咱们说一种土方法。

class Token(object):
   def __init__(self, user, passwd):
        self.user = user
        self.passwd = passwd
         
    def get_token(self):
        # 1. 用随机字符串和时间戳来区分请求和保证安全
        self.rdm_str = ''.join(random.sample('abcdefghij123456789', 5))
        self.time = int(time.time())
        
        # 2. 加上用户的 passwd 构成一个数组,且按照字母表顺序排序
        token_str_list = [self.passwd, self.rdm_str, str(self.time)]
        token_str_list.sort()
        token_str = ''.join(token_str_list)

        # 3. 生成 hash 值,注意 hash 值中隐含 用户密码 的信息,并没有原生的体现密码
        m1 = md5.new()
        m1.update(token_str)
        self.token = m1.hexdigest()
        return self.token

发送请求:

# USER_NAME 和 PASSWORD  是由服务端分发的
# 客户端:把 token 和 生产token的原始数据(中的随机字符串 和 时间戳)放到请求的 URL 上 ,用户名放到请求体中
# 服务端:收到请求后,从 URL 中解析出 token 和  随机字符串 和 时间戳  从请求体中获得用户名
#        然后查询用户密码表得到该用户对应的密码
#        最后利用 get_token  方法重新计算下 token,从而和请求 URL 中携带的 token 比较
# 关键在于:服务端和客户端计算token的方法必须一样,且用户名和密码由服务端分发
# 优化点:可以把用户名 和 随机字符串 和 时间戳 和 token 都放到请求头中,这样可能更符合 restful 规范
token_obj = Token(USER_NAME, PASSWROD)    
req_url = "http://192.168.0.1/getFlowData/?reqTime=%s&reqToken=%s&reqRandom=%s" % \
           (token_obj.time, token_obj.get_token(), token_obj.rdm_str)
           
post_data = {'username': USERNAME, 'flowNo': self.flow_num}
url_encode = urllib.urlencode(post_data)
req = urllib2.Request(url=req_url, data=url_encode)
res_data = urllib2.urlopen(req)
res = res_data.read()
data_set = json.loads(res)

改进版:替换上面的用户名和密码,可以用 app_name 和 该 app 对应的盐值,同时把生成 token 的原始数据和 token 信息放到请求头里而不是放到请求的 URL 里面。而计算 token 的方法就变成了:

# parms_dict 包括:当前时间,随机字符串,app_name,盐值,注意param_dict是 key 按照字母表顺序排序后的结果,
# 如果不排序的话,客户端和服务端计算出来的值可能就不一样了,因为字典是“键-值对”的无序可变序列
some_param = ["{0}={1}".format(k, v) for k, v in param_dict.iteritems()]

# headers 包括:当前时间,随机字符串,app_name 和根据 parms_dict  计算得到的 token
# 服务端会根据请求头中的 app_name 查库得到盐值,
# 然后按照同样的算法计算 token,然后和请求头里的 token 比对
# 所以要保证 parms_dict  和 headers 中的 当前时间,随机字符串,app_name 的值是一样的
headers['token'] = hashlib.sha1("&".join(some_param).encode()).hexdigest()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值