为什么在Django中使用线程本地化不好? [英] Why is using thread locals in Django bad?

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

问题描述

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



要实现线程本地存储中间件,我遵循Django网站上的一个教程:
http:// code。 djangoproject.com/wiki/CookBookThreadlocalsAndUser?version=18



此文档已被修改为建议避免使用此技术:
http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser?version=20



从文章中:


从设计的角度来看,threadlocals本质上是全局变量,并且受制于全球变量通常需要的所有常见可移植性和可预测性的问题。



Mor重要的是,从安全性的角度来看,线程架构构成了巨大的风险。通过提供暴露其他线程状态的数据存储,您可以为Web服务器中的一个线程提供一种可能修改系统中另一个线程的状态的方法。如果线程数据包含用户或其他认证相关数据的描述,则该数据可以用作授权访问未经授权的用户的攻击的基础,或者暴露用户的私人细节。虽然可以构建一个安全的这种攻击的线程系统,但防御性要容易得多,并且建立一个首先不会受到任何此类漏洞的系统。


我明白为什么全局变量可能不好,但在这种情况下,我在自己的服务器上运行我自己的代码,所以我看不出有什么危险两个全局变量姿势。



有人可以解释涉及的安全问题吗?我已经问很多人,如果他们阅读这篇文章,并且知道我在使用线程本地人,那么他们将如何窃取我的应用程序,但没有人能够告诉我。我开始怀疑这是一个喜欢明确传递对象的发型纯粹主义者的意见。

解决方案

我不同意完全。 TLS非常有用。应谨慎使用,正如全局变量应谨慎使用;但是说它不应该被使用完全是不可思议的,因为不应该使用全局变量。



例如,我将当前活动的请求存储在TLS中。这使得它可以从我的记录类访问,而无需通过每个接口传递请求 - 包括许多不关心Django的界面。它允许我从代码中的任何地方创建日志条目;记录器输出到数据库表,如果在创建日志时发生请求发生活动,则会记录活动用户和正在请求的内容。



如果您不希望一个线程具有修改另一个线程的TLS数据的功能,那么将TLS设置为禁止此操作,这可能需要使用本机TLS类。虽然我没有发现这个说法,如果一个攻击者可以执行任意的Python代码作为你的后端,你的系统已经被致命的破坏了 - 他可以猴子补丁以后再作为一个不同的用户运行。



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


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.

To implement the thread locals storage in a middleware, I followed a tutorial on the Django site: http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser?version=18

This document has since been modified to suggest avoiding this technique: http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser?version=20

From the article:

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.

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.

解决方案

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.

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.

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.

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天全站免登陆