Commits

Yann Malet  committed fb94684

Added a csrf_token management

  • Participants
  • Parent commits 6f0a2eb

Comments (0)

Files changed (2)

File cmd/server.go

 )
 
 func main() {
-	fmt.Println("Reading the routes.")
 	web.App.SetRoute()
-
 	// Start serving
 	fmt.Println("Starting server on : http://127.0.0.1:8080")
-	http.Handle("/", web.App.Router)
+	http.Handle("/", web.App)
 
 	// Serving static file
 	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(web.App.Path+"/web/static/"))))
 	"fmt"
 	"github.com/gorilla/context"
 	"github.com/gorilla/mux"
+	"github.com/gorilla/sessions"
 	"html/template"
 	"net/http"
 	//"os"
+	"crypto/rand"
+	"encoding/base64"
 	"gowiki/pages"
 	"path/filepath"
 )
 
 // Implement a sigleton Pattern
 type WebApp struct {
-	Router  *mux.Router
-	Storage Storage
-	Path    string
+	Router      *mux.Router
+	Storage     Storage
+	Path        string
+	CookieStore *sessions.CookieStore
 }
 
-func NewWebApp() *WebApp {
+func newWebApp() *WebApp {
 	storage, err := NewMemStorage()
 	if err != nil {
 		fmt.Println("An error occured while creating the storage : ", err)
 	//	fmt.Println("An error occured while trying to retireve the current path", err)
 	//}
 	path := "/home/yml/Dropbox/Devs/golang/gorilla_on_web/src/gowiki/"
-
-	return &WebApp{
-		Router:  mux.NewRouter(),
-		Storage: storage,
-		Path:    path}
+	app := &WebApp{
+		Router:      mux.NewRouter(),
+		Storage:     storage,
+		Path:        path,
+		CookieStore: sessions.NewCookieStore([]byte("something-very-secret"))}
+	return app
 }
 
 func (app *WebApp) Template(name string) string {
 	return filepath.Join(app.Path, "web", "templates", name)
 }
 
+func (app *WebApp) GenerateCsrfToken() string {
+	// Arbitrary length of 80
+	token := make([]byte, 80)
+	rand.Read(token)
+	return base64.StdEncoding.EncodeToString(token)
+}
+
 func (app *WebApp) SetRoute() {
 	// request multiplexer
 	app.Router.HandleFunc("/inspect/{slug}/", RequestInspector).Name("inspector")
 	app.Router.HandleFunc("/", Index).Name("index")
 }
 
+func (app *WebApp) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	// Get the session and write a DummyKey
+	session, _ := App.CookieStore.Get(r, "gowiki")
+	csrf_token, ok := session.Values["csrf_token"]
+	if !ok {
+		csrf_token = App.GenerateCsrfToken()
+		session.Values["csrf_token"] = csrf_token
+		App.CookieStore.Save(r, w, session)
+	}
+
+	context.Set(r, "csrf_token", csrf_token)
+	if r.Method == "POST" && r.FormValue("csrf_token") != csrf_token {
+		http.Error(w, "Fobidden", http.StatusForbidden)
+	} else {
+		app.Router.ServeHTTP(w, r)
+	}
+}
+
 // Initialize my app object
-var App = NewWebApp()
+var App = newWebApp()
 
 func RequestInspector(w http.ResponseWriter, r *http.Request) {
-	defer context.Clear(r)
 	fmt.Fprintf(w, "URL: %s, method: %s, vars: %s", r.URL, r.Method, mux.Vars(r))
 }
 
 func Index(w http.ResponseWriter, r *http.Request) {
-	defer context.Clear(r)
 	pages_url, err := App.Router.Get("page_list").URL()
 	if err != nil {
 		panic(err)
 }
 
 func PageList(w http.ResponseWriter, r *http.Request) {
-	defer context.Clear(r)
 	ctx := make(map[string]interface{})
+	ctx["csrf_token"] = context.Get(r, "csrf_token")
 	if r.Method == "POST" {
-		page := pages.Page{r.FormValue("name"), r.FormValue("Slug"), r.FormValue("content")}
+		page := pages.Page{r.FormValue("name"),
+			r.FormValue("slug"),
+			r.FormValue("content")}
+
 		validationErrors, err := page.Validate()
 		if err != nil {
 			ctx["validationErrors"] = validationErrors
 		} else {
 			App.Storage.AddPage(page)
 			// Redirect to / after the creation of the page
-			http.Redirect(w, r, "/", 302)
+			http.Redirect(w, r, "/pages/", 302)
 		}
 	}
 
 }
 
 func PageDetail(w http.ResponseWriter, r *http.Request) {
-	defer context.Clear(r)
 	t, err := template.ParseFiles(
 		App.Template("detail_page.html"), App.Template("base.html"))
 	if err != nil {