为什么在 Django 中使用线程局部变量不好? [英] Why is using thread locals in Django bad?

查看:60
本文介绍了为什么在 Django 中使用线程局部变量不好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用线程局部变量来存储当前用户和请求对象.这样我就可以从程序中的任何地方(例如动态表单)轻松访问请求,而无需传递它们.

I am using thread locals to store the current user and request objects. This way I can have easy access to the request from anywhere in the programme (e.g. dynamic forms) without having to pass them around.

为了在中间件中实现线程本地存储,我遵循了 Django 站点上的教程:https://web.archive.org/web/20091128195932/http://code.djangoproject.com:80/wiki/CookBookThreadlocalsAndUser

To implement the thread locals storage in a middleware, I followed a tutorial on the Django site: https://web.archive.org/web/20091128195932/http://code.djangoproject.com:80/wiki/CookBookThreadlocalsAndUser

此文档已被修改以建议避免使用此技术:https://web.archive.org/web/20110504132459/http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser

This document has since been modified to suggest avoiding this technique: https://web.archive.org/web/20110504132459/http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser

来自文章:

从设计的角度来看,线程局部变量本质上是全局变量,并且会遇到全局变量通常带来的所有常见的可移植性和可预测性问题.

From a design point of view, threadlocals are essentially global variables, and are subject to all the usual problems of portability and predictability that global variables usually entail.

更重要的是,从安全的角度来看,threadlocals 带来了巨大的风险.通过提供一个公开其他线程状态的数据存储,您可以为 Web 服务器中的一个线程提供一种方法来潜在地修改系统中另一个线程的状态.如果线程本地数据包含用户的描述或其他与身份验证相关的数据,则该数据可能被用作授予未授权用户访问权限或暴露用户私人详细信息的攻击的基础.虽然可以构建一个不受此类攻击的线程本地系统,但防御并构建一个首先不受任何此类漏洞影响的系统要容易得多.

More importantly, from a security point of view, threadlocals pose a huge risk. By providing an data store that exposes the state of other threads, you provide a way for one thread in your web server to potentially modify the state of another thread in the system. If the threadlocal data contains descriptions of users or other authentication-related data, that data could be used as the basis for an attack that grants access to an unauthorized user, or exposes private details of a user. While it is possible to build a threadlocal system that is safe from this sort of attack, it's a lot easier to be defensive and build a system that isn't subject to any such vulnerability in the first place.

我理解为什么全局变量可能不好,但在这种情况下,我在自己的服务器上运行自己的代码,所以我看不到两个全局变量会带来什么危险.

I understand why global variables can be bad, but in this case I'm running my own code on my own server so I can't see what danger two global variables pose.

有人可以解释所涉及的安全问题吗?我问过很多人,如果他们阅读了这篇文章并且知道我在使用线程局部变量,他们将如何破解我的应用程序,但没有人能够告诉我.我开始怀疑这是喜欢明确传递对象的头发分裂纯粹主义者的观点.

Can someone explain the security issue involved? I have asked many people how they would hack my application if they read this article and know I'm using thread locals, yet no one has been able to tell me. I am starting to suspect that this is an opinion held by hair-splitting purists who love to pass objects explicitly.

推荐答案

我完全不同意.TLS 非常有用.应该谨慎使用它,就像应该谨慎使用全局变量一样;但是说根本不应该使用它就像说永远不应该使用全局变量一样荒谬.

I disagree entirely. TLS is extremely useful. It should be used with care, just as globals should be used with care; but saying it shouldn't be used at all is just as ridiculous as saying globals should never be used.

例如,我将当前活动的请求存储在 TLS 中.这使得它可以从我的日志类访问,而不必通过每个接口传递请求——包括许多根本不关心 Django 的接口.它让我可以从代码中的任何地方创建日志条目;记录器输出到数据库表,如果创建日志时请求恰好处于活动状态,它会记录诸如活动用户和请求的内容之类的信息.

For example, I store the currently active request in TLS. This makes it accessible from my logging class, without having to pass the request around through every single interface--including many that don't care about Django at all. It lets me make log entries from anywhere in the code; the logger outputs to a database table, and if a request happens to be active when a log is made, it logs things like the active user and what was being requested.

如果您不希望一个线程具有修改另一个线程的 TLS 数据的能力,则将您的 TLS 设置为禁止此操作,这可能需要使用本机 TLS 类.不过,我认为这个论点并不令人信服.如果攻击者可以执行任意 Python 代码作为您的后端,那么您的系统就已经受到了致命的威胁——例如,他可以修补任何东西以便稍后以不同的用户身份运行.

If you don't want one thread to have the capability of modifying another thread's TLS data, then set your TLS up to prohibit this, which probably requires using a native TLS class. I don't find that argument convincing, though; if an attacker can execute arbitrary Python code as your backend, your system is already fatally compromised--he could monkey patch anything to be run later as a different user, for example.

显然,您需要在请求结束时清除所有 TLS;在 Django 中,这意味着在中间件类中的 process_response 和 process_exception 中清除它.

Obviously, you'll want to clear any TLS at the end of a request; in Django, that means clearing it in process_response and process_exception in a middleware class.

这篇关于为什么在 Django 中使用线程局部变量不好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆