add nonce support with safe CSP

This commit is contained in:
Simon Rieger 2024-04-01 12:58:36 +02:00
parent 074fad28bd
commit d27d29ae34
4 changed files with 68 additions and 2 deletions

View file

@ -19,6 +19,7 @@ services:
volumes:
- ./uploads:/uploads
- ./templates:/templates
- ./static:/static
restart: always

View file

@ -12,6 +12,8 @@ import (
"strings"
"sync"
"time"
"crypto/rand"
"encoding/base64"
)
var (
@ -25,6 +27,9 @@ func main() {
http.HandleFunc("/upload", uploadHandler)
http.HandleFunc("/image/", imageHandler)
http.HandleFunc("/view/", viewHandler)
// Statischen Dateipfad setzen
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
fmt.Println("Server listening on :8080")
http.ListenAndServe(":8080", nil)
@ -53,9 +58,28 @@ func homeHandler(w http.ResponseWriter, r *http.Request) {
}
}
func generateNonce() (string, error) {
nonceBytes := make([]byte, 16) // 16 Bytes generieren eine ausreichend lange Zeichenfolge für den Nonce
if _, err := rand.Read(nonceBytes); err != nil {
return "", err // Im Fehlerfall, geben Sie den Fehler zurück
}
return base64.StdEncoding.EncodeToString(nonceBytes), nil
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
nonce, err := generateNonce()
if err != nil {
// Fehlerbehandlung, z.B. Senden eines Serverfehlers
http.Error(w, "Serverfehler", http.StatusInternalServerError)
log.Printf("Fehler beim Generieren des Nonce: %v", err)
return
}
// Setzen der Content Security Policy
w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'none';")
//w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'none';")
//w.Header().Set("Content-Security-Policy", fmt.Sprintf("default-src 'self'; script-src 'self' 'nonce-%s'; object-src 'none';", nonce))
w.Header().Set("Content-Security-Policy", fmt.Sprintf("script-src 'self' 'nonce-%s';", nonce))
mu.Lock()
defer mu.Unlock()
@ -139,9 +163,11 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
data := struct {
Message string
Filename string
Nonce string
}{
Message: "Bild erfolgreich hochgeladen.",
Filename: filename, // Geändert, um den möglicherweise modifizierten Dateinamen anzuzeigen
Nonce: nonce,
}
err = tmpl.Execute(w, data)

15
static/js/script.js Normal file
View file

@ -0,0 +1,15 @@
document.addEventListener('DOMContentLoaded', (event) => {
document.getElementById('copyButton').addEventListener('click', kopiereURL);
});
function kopiereURL() {
var copyText = document.getElementById("imageURL");
copyText.select();
copyText.setSelectionRange(0, 99999); // Für mobile Geräte
navigator.clipboard.writeText(copyText.value).then(function() {
console.log('Kopieren in die Zwischenablage erfolgreich.');
}, function(err) {
console.error('Fehler beim Kopieren in die Zwischenablage: ', err);
});
}

View file

@ -5,7 +5,31 @@
</head>
<body>
<p>{{.Message}}</p>
<a href="/view/{{.Filename}}">Ihr Bild anzeigen</a>
<!-- Anzeigen des Links zum Bild, um es zu betrachten -->
<p><a href="/view/{{.Filename}}" target="_blank">Ihr Bild anzeigen</a></p>
<!-- Eingabefeld mit der URL des Bildes -->
<input type="text" value="https://pick.brothertec.eu/view/{{.Filename}}" id="imageURL" readonly>
<!-- Button, um die URL zu kopieren -->
<button id="copyButton">URL kopieren</button>
<p><a href="/upload">Zurück zum Upload</a></p>
<script src="/static/js/script.js" nonce="{{.Nonce}}"></script>
<!-- <script type="text/javascript" nonce="{{.Nonce}}">
function kopiereURL() {
// Finde das Textfeld mit der URL
var copyText = document.getElementById("imageURL");
// Wähle den Text innerhalb des Textfeldes
copyText.select();
copyText.setSelectionRange(0, 99999); // Für mobile Geräte
// Versuche, den Text ins Clipboard zu kopieren
navigator.clipboard.writeText(copyText.value).then(function() {
console.log('Kopieren in die Zwischenablage erfolgreich.');
}, function(err) {
console.error('Fehler beim Kopieren in die Zwischenablage: ', err);
});
}
</script> -->
</body>
</html>