赞
踩
最近查阅项目日志时,我发现了一些奇怪的请求,比如有人访问了 "/robot.txt"。由于之前了解过渗透测试,我猜测可能有人使用自动扫描工具尝试对我的项目进行扫描。
为了解决这个问题,我考虑了一些解决思路。首先,在前端方面,我打算对接口进行加密。具体做法是统一拦截所有的http请求,在请求头中添加时间戳。然后,我会将这个时间戳与当前的实时时间进行对比,如果超过了我所定义的时间范围,就会抛出错误。此外,我还会利用哈希算法,结合时间戳和http请求的body或params,生成一个秘钥。这样,在后端接收到请求后,我们可以通过解密和验证数字签名,确保请求的完整性和合法性。
1、首先定义一个js工具函数,利用params, timestamp, secretKey,生成秘钥,详细代码如下:
- import crypto from 'crypto';
-
- export function generateSign(params, timestamp, secretKey) {
- let paramStr = '';
- if (params !== undefined) {
- paramStr = JSON.stringify(params);
- }
- paramStr += String(timestamp);
- paramStr += secretKey;
- // console.log("加密前组装",paramStr)
- console.log("加密后结果",crypto.createHash('sha256').update(paramStr).digest('hex'))
- return crypto.createHash('sha256').update(paramStr).digest('hex');
- }
2、需要在vue项目的请求拦截器添加处理之后的秘钥,详情如下:
- import { generateSign } from './sign.js'
- const secretKey = 'your-secret-key';
-
- class Http {
- constructor() {
- this.http = axios.create({
- baseURL: backURL,
- timeout:100000
- })
-
- // 设置拦截器,用来添加JWT Token的
- this.http.interceptors.request.use(config => {
- const token = sessionStorage.getItem("token");
- if (token && token != 'undefined') {
- config.headers.common.Authorization = "Token " + token
- // 获取当前时间戳
- return addSignAndTimestamp(config)
- }
- return addSignAndTimestamp(config)
- },error =>{
- return Promise.reject(error)
- })
-
- function addSignAndTimestamp(config) {
- const timestamp = Date.now();
- let sign;
- if (config.method === 'post' || config.method === 'put') {
- sign = generateSign(config.data, timestamp, secretKey);
- } else {
- sign = generateSign(config.params, timestamp, secretKey);
- }
- config.headers['X-Timestamp'] = timestamp;
- config.headers['X-Sign'] = sign;
- return config;
- }
- }
- }
1、前端使用了hash生成秘钥,在后端也需要同样的算法生成秘钥。
- import hashlib
- import json
-
- def generate_sign(params, timestamp, secret_key):
- param_str = json.dumps(params, separators=(',', ':'), ensure_ascii=False) if params and params != {} else ''
- param_str = f"{param_str}{timestamp}{secret_key}"
- hash_obj = hashlib.sha256(param_str.encode())
- return hash_obj.hexdigest()
2、后端django可以利用中间件在视图层获取到请求之前进行处理
首先,自己定义中间件的内容,尤其需要注意secret_key 需要前后端保持一致。
- import json
- import time
- import hashlib
- from django.http import HttpResponseBadRequest
- from sso.sign import generate_sign
-
-
- class SignatureMiddleware:
- def __init__(self, get_response):
- self.get_response = get_response
- self.secret_key = 'your-secret-key'
-
- def __call__(self, request):
- # # 在请求头中获取签名和时间戳
- timestamp = request.META.get('HTTP_X_TIMESTAMP')
- sign = request.META.get('HTTP_X_SIGN')
-
- if not timestamp or not sign:
- # 如果请求头中没有签名或时间戳,返回错误响应
- return HttpResponseBadRequest('Missing signature or timestamp')
-
- # 构造签名参数
- if request.method == 'GET':
- params = request.GET.dict()
- elif request.method == 'POST':
- params = convert_request_body(request.body)
- elif request.method == 'PUT':
- params = convert_request_body(request.body)
- elif request.method == 'DELETE':
- params = convert_request_body(request.body)
- else:
- # 对于其他请求方法,可以根据需要自行处理
- return HttpResponseBadRequest('no support method')
-
- # 根据请求参数、时间戳和密钥生成签名
- expected_sign = generate_sign(params, timestamp, self.secret_key)
-
- # 验证签名是否正确
- if sign != expected_sign:
- return HttpResponseBadRequest('Invalid signature')
-
- # 验证时间戳是否过期
- now = int(time.time() * 1000)
- if abs(now - int(timestamp)) > 3 * 60 * 1000: # 时间戳有效期为 3 分钟
- return HttpResponseBadRequest('Expired timestamp')
-
- # 如果签名和时间戳均合法,则继续处理请求
- response = self.get_response(request)
- return response
-
-
- def convert_request_body(request_body):
- # 解码请求体字节,如果为空则返回空字典
- body_str = request_body.decode('utf-8') if request_body else ""
- # 将解码后的字符串转换为字典,如果为空则返回空字典
- params = json.loads(body_str) if body_str else ""
- return params
3、在项目的 settings.py添加中间件即可
- MIDDLEWARE = [
- 'sso.SignatureMiddleware.SignatureMiddleware' #自定义的中间件
- ]
通过引入时间戳超时机制和哈希算法数字签名技术,我们有效地防止了重放攻击和请求篡改的风险。这些安全措施不仅保护了项目的机密性和完整性,也提升了用户对项目的信任度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。