Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Python编写具有特定权限的文件_Python_File Io_Permissions - Fatal编程技术网

用Python编写具有特定权限的文件

用Python编写具有特定权限的文件,python,file-io,permissions,Python,File Io,Permissions,我试图创建一个只有用户可读写的文件(0600) 使用os.open()的唯一方法是这样做吗 import os fd = os.open('/path/to/file', os.O_WRONLY, 0o600) myFileObject = os.fdopen(fd) myFileObject.write(...) myFileObject.close() 理想情况下,我希望能够将与关键字一起使用,以便自动关闭对象。有没有更好的方法来完成我上面的工作 更新 各位,虽然我感谢你们的支持,但我自己

我试图创建一个只有用户可读写的文件(
0600

使用
os.open()
的唯一方法是这样做吗

import os
fd = os.open('/path/to/file', os.O_WRONLY, 0o600)
myFileObject = os.fdopen(fd)
myFileObject.write(...)
myFileObject.close()
理想情况下,我希望能够将
关键字一起使用,以便自动关闭对象。有没有更好的方法来完成我上面的工作

更新 各位,虽然我感谢你们的支持,但我自己也不得不反对我最初提出的解决方案。原因是这样做,无论文件存在的时间多么短,并且没有适当的权限,都会有一段时间——这会留下广泛的攻击途径,甚至出现错误行为。
当然,首先创建具有正确权限的文件是一种方法——与此相反,使用Python的
只是一种糖果

所以,请把这个答案作为一个“不做什么”的例子

原创帖子

您可以改用
os.chmod

>>> import os
>>> name = "eek.txt"
>>> with open(name, "wt") as myfile:
...   os.chmod(name, 0o600)
...   myfile.write("eeek")
...
>>> os.system("ls -lh " + name)
-rw------- 1 gwidion gwidion 4 2011-04-11 13:47 eek.txt
0
>>>
(请注意,在Python中使用八进制的方法是显式的——在它前面加上“
0o
”,就像在“
0o600
”。在Python2.x中,只需编写
0600
”就可以了——但这既有误导性又不推荐。)


但是,如果您的安全性很关键,您可能应该像使用
os.open
一样使用
os.fdopen
os.open

返回的文件描述符中检索Python文件对象。问题是什么
file.close()
将关闭该文件,即使该文件是使用
os.open()
打开的

with os.fdopen(os.open('/path/to/file', os.O_WRONLY | os.O_CREAT, 0o600), 'w') as handle:
  handle.write(...)

此答案解决了与的多个问题,尤其是
umask
问题

import os
import stat

# Define file params
fname = '/tmp/myfile'
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL  # Refer to "man 2 open".
mode = stat.S_IRUSR | stat.S_IWUSR  # This is 0o600.
umask = 0o777 ^ mode  # Prevents always downgrading umask to 0.

# For security, remove file with potentially elevated mode
try:
    os.remove(fname)
except OSError:
    pass

# Open file descriptor
umask_original = os.umask(umask)
try:
    fdesc = os.open(fname, flags, mode)
finally:
    os.umask(umask_original)

# Open file handle and write to file
with os.fdopen(fdesc, 'w') as fout:
    fout.write('something\n')
如果所需模式为
0600
,则可以更清楚地将其指定为八进制数
0o600
。更好的是,只需使用
stat
模块

即使第一次删除了旧文件,竞争条件仍然是可能的。在标志中包含带有
os.O_EXCL
os.O_create
将阻止创建由于竞争条件而存在的文件。这是一种必要的二级安全措施,可防止打开可能已存在的文件,该文件可能具有提升的
模式
。在Python 3中,如果文件存在,则会引发带有[Errno 17]的
fileexisterror

如果未能首先将
umask
设置为
0
0o777^模式
,可能会导致
操作系统设置不正确的
模式
(权限)。open
。这是因为默认的
umask
通常不是
0
,它将应用于指定的
模式
。例如,如果我的原始
umask
2
,即
0o002
,并且我指定的模式是
0o222
,如果我未能首先设置
umask
,则生成的文件可以改为具有
0o220
模式,这不是我想要的。根据
man 2 open
,所创建文件的模式为
模式&~umask

umask
将尽快恢复到其原始值。此获取和设置不是线程安全的,在多线程应用程序中必须使用
线程.Lock


有关umask的更多信息,请参阅。

我想建议对a-B-B的优秀答案进行修改,以更清楚地区分关注点。主要的优点是,您可以分别处理打开文件描述符期间发生的异常和实际写入文件期间的其他问题

外部<代码>请尝试。。。最后,
block在打开文件描述符时负责处理权限和
umask
问题。内部
with
块处理在使用Python文件对象时可能出现的异常(正如OP所希望的):

如果要附加到文件而不是写入,则应按如下方式打开文件描述符:

fdesc = os.open(outfname, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600)
with os.fdopen(fdesc, "a") as outf:
文件对象如下所示:

fdesc = os.open(outfname, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600)
with os.fdopen(fdesc, "a") as outf:

当然,所有其他常用的组合都是可能的。

问题在于设置权限,以确保文件不具有全局可读性(仅对当前用户进行读/写)

不幸的是,代码本身:

fd = os.open('/path/to/file', os.O_WRONLY, 0o600)
不保证权限将被拒绝给世界。它确实尝试为当前用户设置r/w(前提是umask允许),仅此而已

在两个完全不同的测试系统上,这段代码创建了一个带有-rw-r--r---rw-rw--的文件,其中包含我的默认umask,以及带有umask(0)的-rw-rw--文件,这显然不是我们想要的(并且会带来严重的安全风险)

如果要确保文件没有为组和世界设置位,则必须首先对这些位进行umask(请记住-umask是拒绝权限):

此外,为了100%确保该文件不存在并具有不同的权限,您必须先对其进行chmod/删除(删除更安全,因为您可能在目标目录中没有写入权限-如果您有安全问题,您不希望在不允许写入的地方写入某些文件!),否则,如果黑客在您移动之前以全球r/w权限创建了文件,您可能会遇到安全问题。在这种情况下,os.open将在不设置权限的情况下打开该文件,您将得到一个世界r/w机密文件

因此,您需要:

import os
if os.path.isfile(file):
    os.remove(file)
original_umask = os.umask(0o177)  # 0o777 ^ 0o600
try:
    handle = os.fdopen(os.open(file, os.O_WRONLY | os.O_CREAT, 0o600), 'w')
finally:
    os.umask(original_umask)
无论您的环境和配置如何,这都是确保创建-rw-------文件的安全方法。当然,您可以根据需要捕获并处理IOR错误。如果您在目标目录中没有写入权限,则无法创建该文件,如果该文件已存在,则删除将失败。

我会采取不同的做法

from contextlib import contextmanager

@contextmanager
def umask_helper(desired_umask):
    """ A little helper to safely set and restore umask(2). """
    try:
        prev_umask = os.umask(desired_umask)
        yield
    finally:
        os.umask(prev_umask)

# ---------------------------------- […] ---------------------------------- #

        […]

        with umask_helper(0o077):
            os.mkdir(os.path.dirname(MY_FILE))
            with open(MY_FILE, 'wt') as f:
                […]

文件操作代码