Heim >Backend-Entwicklung >Golang >Wie kann ich die Dateidekomprimierung mit dem Zip-Paket von Go vereinfachen und sichern?

Wie kann ich die Dateidekomprimierung mit dem Zip-Paket von Go vereinfachen und sichern?

Barbara Streisand
Barbara StreisandOriginal
2024-11-14 14:54:02392Durchsuche

How can I simplify and secure file decompression using Go's zip package?

Einfache und effektive Dateidekomprimierung in Go

Das Dekomprimieren von ZIP-Archiven in Go kann ein unkomplizierter Vorgang sein. Ein Ansatz besteht, wie im Originalcode gezeigt, darin, die Dekomprimierung für jede Datei im Archiv manuell durchzuführen.

Es gibt jedoch eine nahtlosere und effizientere Möglichkeit, dies mit der folgenden aktualisierten Lösung zu erreichen:

func Unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer func() {
        if err := r.Close(); err != nil {
            panic(err)
        }
    }()

    os.MkdirAll(dest, 0755)

    // Closure to wrap file extraction and writing, avoiding deferred stack overflow
    extractAndWriteFile := func(f *zip.File) error {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer func() {
            if err := rc.Close(); err != nil {
                panic(err)
            }
        }()

        path := filepath.Join(dest, f.Name)

        // Check for directory traversal (ZipSlip) vulnerability
        if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
            return fmt.Errorf("illegal file path: %s", path)
        }

        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            os.MkdirAll(filepath.Dir(path), f.Mode())
            f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer func() {
                if err := f.Close(); err != nil {
                    panic(err)
                }
            }()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }

        return nil
    }

    for _, f := range r.File {
        err := extractAndWriteFile(f)
        if err != nil {
            return err
        }
    }

    return nil
}

Diese aktualisierte Lösung bietet mehrere Vorteile:

  • Deferred Close() Behandelte Fehler: Sie behandelt potenzielle Fehler beim Schließen sowohl des Dateireaders (rc) als auch des Archivleser (r), der eine ordnungsgemäße Bereinigung auch bei Fehlern gewährleistet.
  • Abschluss-verpackte Dateiextraktion: Der Extraktions- und Schreibvorgang für jede Datei ist in einem Abschluss gekapselt, wodurch die Es müssen mehrere defer .Close()-Aufrufe für jede Datei gestapelt und bereinigt werden.
  • Verzeichniserstellung: Die Lösung stellt sicher, dass das Zielverzeichnis vor dem Extrahieren von Dateien vorhanden ist, und verhindert so Extraktionsfehler.
  • ZipSlip-Prävention: Enthält eine Sicherheitsüberprüfung, um potenzielle Schwachstellen beim Durchlaufen von Verzeichnissen (ZipSlip) zu verhindern, indem sichergestellt wird, dass Dateien nicht außerhalb des erwarteten Zielverzeichnisses extrahiert werden.

Mit diesen Verbesserungen bietet dieser Code eine einfache, robuste und sichere Methode zum Entpacken von Dateien in Go.

Das obige ist der detaillierte Inhalt vonWie kann ich die Dateidekomprimierung mit dem Zip-Paket von Go vereinfachen und sichern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn