最安全的api接口认证

实现步骤:

1、客户端与服务器都存放着用于验证的Token字段,客户端在本地把自己的 用户名+时间戳+Token 组合进行MD5加密后生成一段新的md5-token。

2、客户端访问的时候携带:用户名、时间戳、md5-token。

3、服务端收到请求后,先判断用户名、时间戳是否合法、假设先判断发送过来的时间戳和现在的时间戳不能大于2分钟。

4、如果是在2分钟之内,到redis里查看有没有该用户为key对应的md5-token,并判断它和发送过来的md5-token是否相同,如果有相同,说明该md5-token已经请求过,不能在操作,如果没找到相同的md5-token,说明是第一次请求,把用户名为key,md5-token为vallue存入redis,存在时间设为2分钟。

5、如果以上都通过了,在去数据库取出用户名和Token字段像客户端一样的方式进行加密。对比两个加密字段,相同则通过验证。

1、例如我们在请求的url后带上 用户名+时间戳+加密的Token

客户端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
BaseDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) Params = {
"server": "127.0.0.1",
"port":8000,
'request_timeout':30,
"urls":{
"asset_report_no_id":"/asset/asset_report_no_id/",
"asset_report":"/asset/asset_report/",
},
'asset_id_path':'%s/var/.asset_id' % BaseDir,
'log_file': '%s/logs/run_log' % BaseDir,
'auth':{
'user':'123456789@qq.com',
'token': 'abc'
},
}
url=http://127.0.0.1:8000/asset/
import hashlib,time
def get_token(username,token_id):
timestamp = int(time.time())
md5_format_str = "%s\n%s\n%s" %(username,timestamp,token_id)
obj = hashlib.md5()
obj.update(md5_format_str)
print "token format:[%s]" % md5_format_str
print "token :[%s]" % obj.hexdigest()
return obj.hexdigest()[10:17], timestamp
def attach_token(url_str):
'''生成一个加密验证在url后'''
user = settings.Params['auth']['user']
token_id = settings.Params['auth']['token'] md5_token,timestamp = get_token(user,token_id)
url_arg_str = "user=%s&timestamp=%s&token=%s" %(user,timestamp,md5_token)
if "?" in url_str:
new_url = url_str + "&" + url_arg_str
else:
new_url = url_str + "?" + url_arg_str
return new_url #生成一个带着加密token的url
url = attach_token(url)

发送请求

data_encode = urllib.urlencode(asset_data)#asset_data为要发送的数据
req = urllib2.Request(url=url,data=data_encode)
res_data = urllib2.urlopen(req,timeout=settings.Params['request_timeout'])
callback = res_data.read()
callback = json.loads(callback)
print (callback)

服务端

2、我们给服务端写一个装饰器token_required,用来验证

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time,hashlib,json
from asset import models
from django.shortcuts import render,HttpResponse
from cmdb import settings
from django.core.exceptions import ObjectDoesNotExist def gen_token(username,timestamp,token):
token_format = "%s\n%s\n%s" %(username,timestamp,token)
obj = hashlib.md5()
obj.update(token_format)
return obj.hexdigest()[10:17] def token_required(func):
def wrapper(*args,**kwargs):
response = {"errors":[]}
get_args = args[0].GET
username = get_args.get("user")
token_md5_from_client = get_args.get("token")
timestamp = get_args.get("timestamp") if not username or not timestamp or not token_md5_from_client:
response['errors'].append({"auth_failed":"This api requires token authentication!"})
return HttpResponse(json.dumps(response))
try:
if abs(time.time() - int(timestamp)) > settings.TOKEN_TIMEOUT:#验证时间有没有超过2分钟
response['errors'].append({"auth_failed":"The token is expired!"})
else:
'''如果没超过两分钟,检查redis里有没有这个加密token'''
red_result = __redies_token(username,token_md5_from_client)
if red_result: #等于True说明是第一次请求,进入下一步验证
user_obj = models.MyUser.objects.get(email=username)
token_md5_from_server = gen_token(username,timestamp,user_obj.token)
if token_md5_from_client != token_md5_from_server:
response['errors'].append({"auth_failed":"Invalid username or token_id"})
else: print("通过验证")
else:
response['errors'].append({"auth_failed":"The token is expired!"}) print("\033[41;1m;%s ---client:%s\033[0m" %(time.time(),timestamp), time.time() - int(timestamp))
except ObjectDoesNotExist as e:
response['errors'].append({"auth_failed":"Invalid username or token_id"})
if response['errors']:
return HttpResponse(json.dumps(response))
else:
return func(*args,**kwargs)
return wrapper def __redies_token(username,token_md5_from_client):
import redis
r = redis.Redis(host='192.168.0.109', port=6379)
val = r.get(username)
if val == token_md5_from_client:
print("是以请求过的token")
return False
else:#不存在,则以用户名为key,加密的token为value存入缓存,存在时间2分钟
r.set(username, token_md5_from_client,ex=120)
return True

最新文章

  1. android 打包失败
  2. 基于HTML5的WebGL呈现A星算法的3D可视化
  3. iOS开发--UIDatePicker
  4. ACM 兄弟郊游问题
  5. contiki-main.c 一 打印观察 <contiki学习之五>
  6. css重点
  7. 谱聚类--SpectralClustering
  8. distributor之Interrupt Set/Clear-Active Registers, GICD_IS/CACTIVERn
  9. Possible concurrency problem: Replicated version id X matches in-memory version for session ...
  10. POJ 2594 Treasure Exploration(最小路径覆盖变形)
  11. laravel框架cookie应用到中间件的理解
  12. EF Fluent API
  13. Vue学习三:v-on:click命令及v-html命令学习
  14. 【CAS单点登录视频教程】 第01集-- 认识CAS
  15. 压力测试工具JMeter入门教程<转>
  16. QuantLib 金融计算——收益率曲线之构建曲线(1)
  17. iOS图片上传及处理
  18. SpringInAction--Bean自动装配的歧义性处理
  19. python安装BeautifulSoup
  20. File I/O的总结

热门文章

  1. POJ 3667 线段树的区间合并简单问题
  2. SA模板
  3. BZOJ3126: [Usaco2013 Open]Photo
  4. 创建SSH keys
  5. BZOJ 4894 有向图 外向生成树个数
  6. HDU 6370 dfs+并查集
  7. Max Sum Plus Plus-HDU1024(dp)
  8. request对象学习
  9. python第四讲
  10. python手记(53)