package main import ( "fmt" "html/template" "io/ioutil" "log" "net/http" "path/filepath" "strings" "time" "github.com/dgrijalva/jwt-go" ) var ( password = "hardcodedpassword" lootPath = "Loot" sessionCookieName = "auth_session" secretKey = []byte("key")) type PageData struct { UIDs []string Files []string } type Claims struct { Username string `json:"username"` jwt.StandardClaims } func main() { http.HandleFunc("/", logMiddleware(loginHandler)) http.HandleFunc("/loot", logMiddleware(lootHandler)) http.HandleFunc("/logout", logMiddleware(logoutHandler)) http.HandleFunc("/files/", logMiddleware(fileHandler)) log.Fatal(http.ListenAndServe(":5647", nil)) fmt.Println("Server started") } func logMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { log.Printf("[%s] %s %s\n", r.Method, r.RemoteAddr, r.URL.Path) next(w, r) } } func loginHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { renderTemplate(w, "login.html", nil) return } if r.FormValue("password") == password { expirationTime := time.Now().Add(1 * time.Hour) claims := &Claims{ Username: "root", StandardClaims: jwt.StandardClaims{ ExpiresAt: expirationTime.Unix(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(secretKey) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } http.SetCookie(w, &http.Cookie{ Name: sessionCookieName, Value: tokenString, Expires: expirationTime, Path: "/", }) http.Redirect(w, r, "/loot", http.StatusSeeOther) return } renderTemplate(w, "login.html", "Incorrect password") } func lootHandler(w http.ResponseWriter, r *http.Request) { checkAuth(w, r) uids, err := getDeviceUIDs() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } data := PageData{UIDs: uids} renderTemplate(w, "loot.html", data) } func fileHandler(w http.ResponseWriter, r *http.Request) { checkAuth(w, r) requestedPath := strings.TrimPrefix(r.URL.Path, "/files/") filePath := filepath.Join(lootPath, requestedPath) http.ServeFile(w, r, filePath) } func logoutHandler(w http.ResponseWriter, r *http.Request) { http.SetCookie(w, &http.Cookie{ Name: sessionCookieName, Value: "", Path: "/", MaxAge: -1, }) http.Redirect(w, r, "/", http.StatusSeeOther) } func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) { t, err := template.ParseFiles(tmpl) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } t.Execute(w, data) } func isAuthenticated(r *http.Request) bool { sessionCookie, err := r.Cookie(sessionCookieName) if err != nil { return false } tokenString := sessionCookie.Value token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { return secretKey, nil }) if err != nil || !token.Valid { return false } return true } func getDeviceUIDs() ([]string, error) { var uids []string files, err := ioutil.ReadDir(lootPath) if err != nil { return nil, err } for _, file := range files { if file.IsDir() { uids = append(uids, file.Name()) } } return uids, nil } func checkAuth(w http.ResponseWriter, r *http.Request) { if !isAuthenticated(r) { http.Redirect(w, r, "/", http.StatusSeeOther) return } }