Is there a well-defined way to check if a path is

2019-06-14 14:52发布

问题:

I'm trying to check if a given user-supplied string is a simple file/folder name. I plan on using os.path.join() to concatenate this name to a preset root directory, but I want to detect and prohibit paths that try to traverse anywhere outside of that root directory.

For example, a string with the value 'track001.mp3' would be fine, it would resolve to 'root_dir/track001.mp3'. However, these should be detected and disallowed:

'../other_root_dir/'
'/etc'
'/'
'~'
'subdir/inner_file'

回答1:

I would advise you to create the path string as you normally would assuming that the user is behaving (e.g. passing a "simple" or conforming path name). Then I'd use os.path.expandvars and os.path.normpath to get the actual path name. Finally, I'd check to make sure that the actual path name resides within the root directory. Something like:

from os.path import expandvars, normpath, join

ROOT_DIR = 'root_dir'

user_path = 'some_path'
test_path = normpath(expandvars(join(ROOT_DIR, user_path)))

expected_prefix = normpath(ROOT_DIR)
if not test_path.startswith(expected_prefix):
    raise ValueError(f'Invalid path "{user_path}"')  # python3.6 f-string.