如何通过Stripe信号安全执行Django视图 防范未授权访问
Django帖子付费解锁功能安全改造实现方向
原有实现的核心漏洞
这套逻辑的致命问题是完全信任前端传递的支付成功状态,根本没在后端侧核实支付真实性,攻击者不需要真的付费,只要构造对应请求就能直接解锁内容。之前尝试加request.is_ajax()判断拦截非AJAX请求的方案没用,这类前端层面的校验都可以通过伪造请求头绕过去,没法从根源解决未授权访问问题。
原有存在漏洞的视图代码:
def unlockpostview(request, post_id): if userthatisunlockingprofile in post.unlockedby.all(): pass else: post.unlockedby.add(userthatisunlockingprofile)
原有存在风险的前端调用逻辑:
if (result.paymentIntent.status === 'succeeded') { $.get("{% url 'postsapp:unlockpostview' post.post_id %}") window.alert("Unlocked") }
基于Stripe服务端Webhook的正确实现方向
- 直接废弃原来给前端调用的解锁接口,核心的「给用户添加帖子解锁权限」逻辑,绝对不能绑定到任何前端可以直接访问的公开路由上
- 在Django后端新增专门的Stripe Webhook接收端点,这个端点只接收Stripe官方服务器主动推送的事件,不处理前端发起的业务请求
- 所有发到Webhook端点的请求必须做强制签名校验:从Stripe后台获取对应Webhook的签名密钥,每次收到请求先验签,确认请求确实是Stripe发的、内容没被篡改,验签不通过直接拒绝处理
- 创建Stripe支付单(不管是PaymentIntent还是Checkout Session)的时候,就把当前发起支付的用户ID、待解锁的帖子ID作为自定义元数据绑到支付对象上,后续收到事件时才能准确匹配对应关系
- Webhook端点只处理Stripe推送的支付成功类事件(比如
payment_intent.succeeded、checkout.session.completed),解析事件里的元数据拿到用户ID和帖子ID,再核对支付金额、关联商品信息都对得上,再执行把用户加入帖子unlockedby列表的操作 - 前端监听到支付成功状态后,只需要做弹窗提示、刷新页面展示内容这类UI交互就行,完全不用承担触发权限开通的职责。就算前端因为网络问题没触发回调,只要Stripe把支付成功的事件推过来,后端就要能正常给用户开权限,避免出现用户付了费却没拿到解锁权限的问题
核心原则:永远不要信任前端传递的支付结果,所有支付状态的判定,都必须以后端从Stripe官方获取的可信数据为准
内容的提问来源于stack exchange,提问作者Vinko Oakniiv
相关产品推荐
相关产品推荐

