Pregunta

He estado tratando de averiguar forma en que los 'mejores prácticas' para gestionar la carga de archivos con TurboGears 2 y hasta el momento se han encontrado no es realmente ningún ejemplo. He descubierto una manera de cargar el archivo de hecho, pero no estoy seguro de qué tan confiable nosotros.

Además, lo que sería una buena manera de obtener el nombre archivos subidos?

    file = request.POST['file']
    permanent_file = open(os.path.join(asset_dirname,
        file.filename.lstrip(os.sep)), 'w')
    shutil.copyfileobj(file.file, permanent_file)
    file.file.close()
    this_file = self.request.params["file"].filename 
    permanent_file.close()

Así que asumiendo que estoy entendiendo correctamente, sería algo como esto evite el núcleo 'nombrar' problema? id = UUID.

    file = request.POST['file']
    permanent_file = open(os.path.join(asset_dirname,
        id.lstrip(os.sep)), 'w')
    shutil.copyfileobj(file.file, permanent_file)
    file.file.close()
    this_file = file.filename
    permanent_file.close()
¿Fue útil?

Solución

@mhawke - tienes razón usted tiene que manejar eso - depende de lo que está haciendo con el archivo, si es que no importa si hay un conflicto de nombres por ejemplo, que sólo se preocupan por la versión más reciente de algunos datos a continuación theres probablemente ningún problema, o si el nombre de archivo no es realmente importante sólo el contenido del archivo, pero aún es una mala práctica.

Se puede usar un archivo temporal nombrado en un dir tmp, a continuación, mover el archivo una vez validado para su ubicación final. O se puede comprobar el nombre de archivo no existe ya, así:

file.name = slugify(myfile.filename)
name, ext = os.path.splitext(file.name)
while os.path.exists(os.path.join(permanent_store, file.name)):
    name += '_'
    file.name = name + ext

raw_file = os.path.join(permanent_store, file.name)

El método slugify sería utilizado para poner en orden el nombre del archivo ...

Otros consejos

Sólo quiero cualquiera que viene aquí en busca de respuestas, para saber que Allesandro Molina 's gran biblioteca Depot constituye la mejor respuesta a esta pregunta.

Se resuelve tanto la denominación y los problemas de copia, y se incorporará muy bien en su aplicación TurboGears. Se puede utilizar con MongoDB GridFS, como en este ejemplo:

from depot.manager import DepotManager

# Configure a *default* depot to store files on MongoDB GridFS
DepotManager.configure('default', {
    'depot.backend': 'depot.io.gridfs.GridFSStorage',
    'depot.mongouri': 'mongodb://localhost/db'
})

depot = DepotManager.get()

# Save the file and get the fileid
fileid = depot.create(open('/tmp/file.png'))

# Get the file back
stored_file = depot.get(fileid)
print stored_file.filename
print stored_file.content_type

o se puede crear fácilmente los campos de fijación en sus modelos SQLAlchemy , como:

from depot.fields.sqlalchemy import UploadedFileField

class Document(Base):
    __tablename__ = 'document'

    uid = Column(Integer, autoincrement=True, primary_key=True)
    name = Column(Unicode(16), unique=True)

    content = Column(UploadedFileField)

... y luego, el almacenamiento de documentos con archivos adjuntos (la fuente puede ser un archivo o bytes) se vuelve tan fácil como:

doc = Document(name=u'Foo', content=open('/tmp/document.xls'))
DBSession.add(doc)

Depot apoya tanto LocalFileStorage, MongoDB 's GridFSStorage , y de Amazon S3Storage . Y, al menos para los archivos almacenados localmente y en S3, el fileid será generado por uuid.uuid1().

No sé mucho acerca de TurboGears y si se puede dar nada para evitar lo siguiente, pero me parece que este código está lleno de peligros. Puede ser posible que un usuario malicioso para sobreescribir (o crear) cualquier archivo de ese proceso pitón los TurboGears tiene acceso de escritura.

¿Qué pasa si es asset_dirname /tmp, el contenido de file.filename es ../../../../../../../etc/passwd y el contenido del archivo root::0:0:root:/root:/bin/bash? En un entorno UNIX Este código (permisos pendientes) abrirían la /tmp/../../../../../../../etc/passwd archivo en modo truncado y luego copiar el contenido del archivo subido a ella - la sobreescritura de archivos de manera efectiva por contraseña del sistema y especificar un usuario root sin una contraseña. Es de suponer que hay cosas desagradables que se pueden hacer para una máquina de Windows también.

OK, esto es un ejemplo extremo que requiere que Python se ejecuta como root (nadie hace eso, ¿verdad?). Incluso si pitón se está ejecutando como un usuario bajo priveleged, archivos subidos con anterioridad, podría ser sobrescrito a voluntad.

Para resumir, no la entrada del usuario de confianza, en este caso el nombre del archivo suministrado por el usuario que está disponible en file.filename.

No es sólo TurboGears pilones con extras? Se puede consultar la ayuda no:

http://wiki.pylonshq.com/display/pylonsdocs / + Form Handling # archivos subidos

Sin embargo, que aún tiene el potencial de falla de seguridad que mhawke mencionado:

os.path.join(permanent_store, myfile.filename.lstrip(os.sep))

Igual que el anterior, si realmente el nombre de archivo de alguna manera era ../../../../../etc/passwd entonces usted podría reemplazar ese archivo ...

Por lo que sólo puede obtener el nombre de archivo real de esta manera:

os.path.join(permanent_store, myfile.filename.split(os.sep).pop())

Werkzeug tiene una muy buena función auxiliar para fijar nombres de los archivos llamados secure_filename . Creo que se puede adoptar y utilizar la misma.

acerca de cómo ir, yo diría segundo buenas las respuestas ya dadas.

Esta es mi 2 peniques sobre la nomenclatura de archivos almacenados.

hecho de guardar el archivo con el nombre original puede provocar una vulnerabilidad. El único uso que hago del nombre original, en todo caso, es dar a entender la detección de tipos MIME.

de todos modos los archivos que se guarden debe dar nombres únicos, por una identidad de grabación o algo similar, y se mantienen en un lugar bajo el control del propietario del directorio de aplicaciones, que es un usuario regular, o en algún otro servicio de almacenamiento, como el depósito antes mencionado etc.

que es una cuestión de diseño del sistema de la lengua buena cruz:.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top