下载鸥 > 网站下载 > 开发教程 > Python

网站安全之怎样在django的jwt中加入指纹绑定

32 2025-03-28 18:07:47

收藏
网站安全之怎样在django的jwt中加入指纹绑定
在 Django 中使用 JWT 时加入**指纹绑定(Token Binding)**是一种有效的安全增强手段,它通过将客户端的唯一特征(如 User-Agent、IP 或自定义指纹)嵌入 Token,并在每次请求时验证其一致性,从而防止 Token 被劫持后在其他设备上滥用。
 

指纹绑定的核心原理

生成阶段:在签发 JWT 时,将客户端特征(指纹)加入 Token 的 payload
验证阶段:每次请求时,比对客户端当前特征与 Token 中的指纹是否一致

关键特征:
User-Agent + IP 地址(简单但有效)

设备指纹(通过 JavaScript 生成更复杂的哈希)

 

具体实现步骤

(1) 自定义 Token 生成逻辑
# utils/tokens.py
from rest_framework_simplejwt.tokens import AccessToken
from hashlib import sha256

class FingerprintedAccessToken(AccessToken):
    def __init__(self, user, request=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # 生成指纹(示例:User-Agent + IP 的哈希)
        if request:
            fingerprint_source = f"{request.META.get('HTTP_USER_AGENT')}:{request.META.get('REMOTE_ADDR')}"
            self.payload['fingerprint'] = sha256(fingerprint_source.encode()).hexdigest()
        
        # 绑定用户ID
        self.payload['user_id'] = user.id


(2) 创建自定义认证后端
# authentication.py
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.exceptions import AuthenticationFailed

class FingerprintJWTAuthentication(JWTAuthentication):
    def get_user(self, validated_token):
        user = super().get_user(validated_token)
        
        # 获取当前请求指纹
        request = self.request
        current_fp_source = f"{request.META.get('HTTP_USER_AGENT')}:{request.META.get('REMOTE_ADDR')}"
        current_fp = sha256(current_fp_source.encode()).hexdigest()
        
        # 验证指纹
        if validated_token.get('fingerprint') != current_fp:
            raise AuthenticationFailed("Token 指纹不匹配,可能已被盗用")
            
        return user


(3) 修改登录视图
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from utils.tokens import FingerprintedAccessToken

class LoginView(APIView):
    def post(self, request):
        user = authenticate(username=request.data['username'], password=request.data['password'])
        if not user:
            return Response({"error": "认证失败"}, status=401)
        
        # 生成带指纹的 Token
        access = FingerprintedAccessToken(user, request=request)
        refresh = FingerprintedRefreshToken(user, request=request)  # 同样实现RefreshToken
        
        return Response({
            "access": str(access),
            "refresh": str(refresh)
        })

(4) 配置 DRF 使用自定义认证
# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'yourapp.authentication.FingerprintJWTAuthentication',  # 替换默认JWT认证
    ]
}
 

进阶优化方案

(1) 动态设备指纹(前端配合)
// 前端生成设备指纹(示例)
function generateFingerprint() {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  ctx.fillText('Fingerprint', 10, 10);
  return canvas.toDataURL().hashCode(); // 简单哈希生成
}

// 登录时附加指纹
fetch('/api/login', {
  method: 'POST',
  headers: {
    'X-Device-Fingerprint': generateFingerprint() 
  }
})


后端处理:
# 修改指纹生成逻辑
fingerprint_source = f"{request.META.get('HTTP_USER_AGENT')}:{request.headers.get('X-Device-Fingerprint')}"

(2) 指纹白名单机制
# models.py
from django.db import models

class AllowedDevice(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    fingerprint = models.CharField(max_length=64)  # 存储指纹哈希
    last_used = models.DateTimeField(auto_now=True)

# authentication.py 中增加检查
if not AllowedDevice.objects.filter(user=user, fingerprint=current_fp).exists():
    raise AuthenticationFailed("未授权的设备")


(3) 指纹漂移容忍
# 允许IP在一定范围内变化(如动态IP)
def is_fingerprint_valid(saved_fp, current_fp):
    # 简单实现:比对除IP外的部分
    saved_parts = saved_fp.split(':')
    current_parts = current_fp.split(':')
    return saved_parts[0] == current_parts[0]  # 只比较User-Agent部分
 

安全增强组合拳

措施    实现方式    防护效果
短期 Token    设置 ACCESS_TOKEN_LIFETIME=15min    减少暴露窗口期
强制刷新    每次刷新 Token 时生成新指纹    防止长期劫持
关键操作验证    敏感操作(如支付)要求二次认证(短信/邮箱)    纵深防御
日志监控    记录所有指纹变更事件    便于事后审计
 

测试与验证

(1) 测试用例示例
# tests.py
from django.test import TestCase
from utils.tokens import FingerprintedAccessToken

class TestFingerprint(TestCase):
    def test_token_reuse(self):
        user = User.objects.create(username="test")
        request1 = self.factory.get('/', HTTP_USER_AGENT='Mozilla', REMOTE_ADDR='192.168.1.1')
        token = FingerprintedAccessToken(user, request=request1)
        
        # 模拟不同设备使用同一Token
        request2 = self.factory.get('/', HTTP_USER_AGENT='Chrome', REMOTE_ADDR='192.168.1.2')
        request2.META['HTTP_AUTHORIZATION'] = f'Bearer {str(token)}'
        
        response = self.client.get('/protected', **{'HTTP_AUTHORIZATION': f'Bearer {str(token)}'})
        self.assertEqual(response.status_code, 401)  # 应拒绝访问


(2) 实际效果验证
合法请求:相同设备+IP 的 Token 正常使用
劫持场景:攻击者复制 Token 到其他设备 → 访问被拒
用户 IP 变化但 User-Agent 不变 → 根据策略允许/拒绝


注意事项
移动端特殊处理:移动网络 IP 变化频繁,建议:
放宽 IP 检查规则
改用设备唯一标识(如 Android ID 或 iOS IDFV)


用户体验平衡:
# 部分接口放宽检查(如公开API)
class SomeView(APIView):
    authentication_classes = []  # 禁用指纹验证
 

性能影响

每次请求需要计算哈希 → 增加 1-3ms 延迟
可缓存指纹验证结果(如 5 分钟内同一 Token 免检)
 

总结

通过指纹绑定,即使 JWT 被窃取,攻击者也因无法复制客户端特征(如精确的 User-Agent + IP 组合)而无法滥用。这种方案在不显著影响用户体验的前提下,大幅提升了安全性。实际项目中建议:

基础版:实施 User-Agent + IP 绑定
高安全需求:增加 前端生成设备指纹
关键系统:结合 二次认证 和 行为分析

这样,我们就进一步保障了Django项目的安全。

本文地址:https://xzo.com.cn/develop/python/1273.html

有帮助,很赞!

信息来源:下载鸥
导出教程 下载word版教程
发表评论 共有条评论
关于Python

Python免费、开源、简单,且含有海量的库。其功能也十分强大,不仅可以做网站、做爬虫、还可以做大数据、做人脸识别,等等等等。如果是新手入门,我们建议是首选Python。

推荐Python开发教程
Python中文分词器准确度与性能测试(jieba、FoolNLTK、HanLP、THULAC、nlpir、ltp)
Python中文分词器准确度与性能测试(jieba、FoolNLTK、HanLP、THULAC、nlpir、ltp)

国内知名度比较高的Python中文分词有哈工大LTP、中科院计算所NLPIR、清华大...

0 517
结巴分词的全模式、精确模式和搜索引擎模式用法与实例
结巴分词的全模式、精确模式和搜索引擎模式用法与实例

结巴分词支持3种模式:全模式、精确模式和搜索引擎模式,不同的模式效果会有差...

0 337
python多线程的概念与好处
python多线程的概念与好处

但凡对电脑知识了解多一点的朋友可能就听说过进程,而如果对蜘蛛爬虫有了解,那...

0 382
怎样用python爬虫爬取百度搜索图片
怎样用python爬虫爬取百度搜索图片

python爬虫爬取百度图片是很多人python爬虫入门后一个重要的练手项目。一方...

40 337
python爬虫怎样入门?
python爬虫怎样入门?

爬虫软件很多,支持爬虫功能的语言也很多,而用python做爬虫,辅以包罗万象的pyth...

0 390
推荐插件
帝国cms百度AI图像无损放大api接口对接插件
帝国cms百度AI图像无损放大api接口对接插件

通过本插件,可以实现帝国cms网站对接百度云api实现图像无损放大的功能。经过...

0 337
帝国cms网站会员登录与退出历史记录日志插件
帝国cms网站会员登录与退出历史记录日志插件

帝国cms默认只有上次登录时间与ip,没有一个记录清单,所以今天,我们分享这个帝...

0 274
帝国cms联想词搜索高级搜索插件下载
帝国cms联想词搜索高级搜索插件下载

帝国CMS自带的搜索功能虽然强大,但也有很强的局限性 -- 必须关键词完全匹配...

0 611
帝国cms访问统计ip地址链接与封禁插件下载
帝国cms访问统计ip地址链接与封禁插件下载

下载鸥开发了这款帝国cms封禁ip插件,自动记录访问情况,让我们可以更快的识别...

0 862
帝国cms自动生成文章新闻目录插件下载
帝国cms自动生成文章新闻目录插件下载

用户体验是我们的需求,百度蜘蛛的认可更是我们的需求。毕竟,没有收录排名,何来...

0 972
帝国cms批量添加后台用户插件
帝国cms批量添加后台用户插件

使用帝国cms的企业用户、新闻资讯类站点的用户很多,此类站点很多时候需要有...

0 579
帝国cms在线考试系统模板插件
帝国cms在线考试系统模板插件

一直没看到好用的帝国cms在线考试插件,所以自己开发了一款。在线考试插件用...

0 1157
帝国cms智能自动审核按星期几审核指定栏目带推送插件
帝国cms智能自动审核按星期几审核指定栏目带推送插件

采集站的必备资源是自动审核,要做到日收录也离不开定时发布。而本插件的自动...

0 1126
客服QQ:341553759
扫码咨询 常见问题 >
官方交流群:90432500
点击加入