web应用主要面临的安全问题:
1.数据篡改
2.数据窃取
3.重放攻击
4.非法参数提交 (SQL注入,XSS等)
HTTP验证的原理
key:
这个key只能是客户端和服务端知道,否则无法保证请求的合法性验证了。key的生成方式可以根据应用来区分:
传统web应用:服务器可以根据客户端浏览器的信息,结合请求的IP,User-Agent等信息产生一个key。
移动APP应用:可以通过事先约定key的方式(前提不能被反编译),或者通过一些非对称加密来生成一个key
时间戳
服务端和客户端约定一个请求时间范围,超过这个时间段就是非法请求
资产入库时,为了防止他人发送恶意请求,篡改数据,所以我们需要对请求进行http验证
客户端和服务端都保存随机字符串
服务端
import time
from django.shortcuts import render,HttpResponse
from repository import models
from django.conf import settings
# redis/Memcache
api_key_record = {
# "1b96b89695f52ec9de8292a5a7945e38|1501472467.4977243":1501472477.4977243
}
def asset(request):
client_md5_time_key = request.META.get('HTTP_OPENKEY')
client_md5_key,client_ctime = client_md5_time_key.split('|')
client_ctime = float(client_ctime)
server_time = time.time()
# 第一关
if server_time-client_ctime > 10:
return HttpResponse('【第一关】小伙子,别唬我,太长了')
# 第二关
temp = "%s|%s" %(settings.AUTH_KEY,client_ctime,)
m = hashlib.md5()
m.update(bytes(temp,encoding='utf-8'))
server_md5_key = m.hexdigest()
if server_md5_key != client_md5_key:
return HttpResponse('【第二关】小子,你是不是修改时间了')
for k in list(api_key_record.keys()):
v = api_key_record[k]
if server_time > v:
del api_key_record[k]
# 第三关:
if client_md5_time_key in api_key_record:
return HttpResponse('【第三关】有人已经来过了...')
else:
api_key_record[client_md5_time_key] = client_ctime + 10
return HttpResponse('成功')
if server_md5_key != client_md5_key:
return HttpResponse('认证失败...')
客户端
import time
import requests
import hashlib
ctime = time.time()
key = "asdfasdfasdfasdf098712sdfs"
new_key = "%s|%s" %(key,ctime,)
m = hashlib.md5()
m.update(bytes(new_key,encoding='utf-8'))
md5_key = m.hexdigest()
md5_time_key = "%s|%s" %(md5_key,ctime)
print(md5_time_key)
response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':md5_time_key})
print(response.text)
模拟黑客攻击
# 截取随机字符串,放在请求头中
import requests
response = requests.get(
url='http://127.0.0.1:8000/api/asset.html',
headers={"OpenKey":"0895c7e295202eda30678e687cc2c817|1501546586.34368"})
print(response.text)
python AES加密
高级加密标准(Advanced Encryption Standard,AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
AES只是个基本算法,实现AES有若干模式。其中的CBC模式因为其安全性而被TLS(就是https的加密标准)和IPSec(win采用的)作为技术标准。简单地说,CBC使用密码和salt
(起扰乱作用)按固定算法(md5)产生key和iv。然后用key和iv(初始向量,加密第一块
明文)加密(明文)和解密(密文)。
下面介绍python实现的AES加密解密实例,这里采用CBC模式,用到了pycrypto模块
加密
"""
安装模块pycrypto
pip3 install pyCrypto
"""
from Crypto.Cipher import AES
def encrypt(message):
"""
AES加密发送字符串
:param message: (str)传入明文字符串
:return: 密文
"""
# 注意此时的key只能是16个字节
key = b'dfdsdfsasdfdsdfs'
# chuan
cipher = AES.new(key, AES.MODE_CBC, key)
# 要加密的字符串,必须是16个字节或16个字节的倍数
ba_data = bytearray(message,encoding='utf-8')
v1 = len(ba_data)
v2 = v1 % 16
if v2 == 0:
v3 = 16
else:
v3 = 16 - v2
for i in range(v3):
ba_data.append(v3)
final_data = ba_data.decode('utf-8')
# 加密
msg = cipher.encrypt(final_data)
return msg
# ############################## 解密 ##############################
def decrypt(msg):
"""
AES解密
:param msg: 密文
:return: 解密后的字符串
"""
# 注意此时的key只能是16个字节
key = b'dfdsdfsasdfdsdfs'
cipher = AES.new(key, AES.MODE_CBC, key)
result = cipher.decrypt(msg)
data = result[0:-result[-1]] # 巧妙取值
return str(data,encoding='utf-8')
raw = "昌平刘德华"
code_raw = encrypt(raw)
print(raw) # 原数据
print(code_raw) # 加密后的字节
decode_raw = decrypt(code_raw)
print(decode_raw) # 解密后的字符串