如何检查一个目录是否是另一个目录的子目录 [英] How to check whether a directory is a sub directory of another directory

查看:202
本文介绍了如何检查一个目录是否是另一个目录的子目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢在Python中编写一个模板系统,它允许包含文件。

eg

这是一个模板
您可以安全地包含文件safe_include`othertemplate.rst`

你知道,包括文件可能是危险的。例如,如果我在一个Web应用程序中使用模板系统,它允许用户创建自己的模板,他们可能会做一些类似于

 
I想要你的密码:safe_include` / etc / password`

因此,我必须限制包含文件到文件在一个特定的子目录(例如 / home / user / templates

现在的问题是:如何检查, /home/user/templates/includes/inc1.rst 位于 / home / user / templates



下面的代码是否可以正常工作并保证安全?

  import os.path 
$ b def in_directory(file,directory,allow_symlink = False):
#make都是绝对
目录= os.path.abspath(目录)
file = os.path.abspath(file)

#检查文件是否是符号链接,如果是,则返回false如果不允许则返回false
if not allow_symlink a nd os.path.islink(file):
return False

#如果两者的公共前缀等于目录
# /a/b/c/d.rst,目录是/ a / b,常用前缀是/ a / b
return os.path.commonprefix([file,directory])==目录

只要 allow_symlink 为False,就应该是安全的, 我认为。允许符号链接当然会使它不安全,如果用户能够创建这样的链接。

更新 - 解决方案
上面的代码如果中间目录是符号链接,则不起作用。
为防止出现这种情况,您必须使用 realpath 而不是 abspath

UPDATE :添加尾部/目录来解决commonprefix()问题。Reorx指出。

这也使得 allow_symlink 不必要,因为符号链接被扩展到了它们的真正目的地。

  import os.path 
$ b $ def in_directory(file,directory):
#make both absolute $ b $ directory = os.path.join(os.path.realpath(directory),' ')
file = os.path.realpath(file)

#return true,如果两者的公共前缀等于目录
#eg /a/b/c/d.rst,目录是/ a / b,常用前缀是/ a / b
return os.path.commonprefix([file,directory])==目录


解决方案

os.path.realpath(path):返回指定的文件名,消除路径中遇到的任何符号链接(如果它们是由操作系统支持的话)。

在目录和子目录名称上使用它,然后检查后面以前者。

I like to write a template system in Python, which allows to include files.

e.g.

    This is a template
    You can safely include files with safe_include`othertemplate.rst`

As you know, including files might be dangerous. For example, if I use the template system in a web application which allows users to create their own templates, they might do something like

I want your passwords: safe_include`/etc/password`

So therefore, I have to restrict the inclusion of files to files which are for example in a certain subdirectory (e.g. /home/user/templates)

The question is now: How can I check, whether /home/user/templates/includes/inc1.rst is in a subdirectory of /home/user/templates?

Would the following code work and be secure?

import os.path

def in_directory(file, directory, allow_symlink = False):
    #make both absolute    
    directory = os.path.abspath(directory)
    file = os.path.abspath(file)

    #check whether file is a symbolic link, if yes, return false if they are not allowed
    if not allow_symlink and os.path.islink(file):
        return False

    #return true, if the common prefix of both is equal to directory
    #e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b
    return os.path.commonprefix([file, directory]) == directory

As long, as allow_symlink is False, it should be secure, I think. Allowing symlinks of course would make it insecure if the user is able to create such links.

UPDATE - Solution The code above does not work, if intermediate directories are symbolic links. To prevent this, you have to use realpath instead of abspath.

UPDATE: adding a trailing / to directory to solve the problem with commonprefix() Reorx pointed out.

This also makes allow_symlink unnecessary as symlinks are expanded to their real destination

import os.path

def in_directory(file, directory):
    #make both absolute    
    directory = os.path.join(os.path.realpath(directory), '')
    file = os.path.realpath(file)

    #return true, if the common prefix of both is equal to directory
    #e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b
    return os.path.commonprefix([file, directory]) == directory

解决方案

os.path.realpath(path): Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path (if they are supported by the operating system).

Use it on directory and subdirectory name, then check latter starts with former.

这篇关于如何检查一个目录是否是另一个目录的子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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