lets-go:11.7 CSRF

This commit is contained in:
tamsin johnson 2024-02-07 23:04:06 -08:00
parent 7db05bca1d
commit 1a59a9e720
10 changed files with 26 additions and 3 deletions

View File

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/go-playground/form/v4" "github.com/go-playground/form/v4"
"github.com/justinas/nosurf"
) )
// newTemplateData ... // newTemplateData ...
@ -18,6 +19,7 @@ func (app *application) newTemplateData(r *http.Request) templateData {
CurrentYear: time.Now().Year(), CurrentYear: time.Now().Year(),
Flash: app.sessionManager.PopString(r.Context(), "flash"), Flash: app.sessionManager.PopString(r.Context(), "flash"),
IsAuthenticated: app.isAuthenticated(r), IsAuthenticated: app.isAuthenticated(r),
CSRFToken: nosurf.Token(r),
} }
} }

View File

@ -3,6 +3,8 @@ package main
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/justinas/nosurf"
) )
// logRequest ... // logRequest ...
@ -59,3 +61,14 @@ func (app *application) requireAuthentication(next http.Handler) http.Handler {
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }
func noSurf(next http.Handler) http.Handler {
csrfHandler := nosurf.New(next)
csrfHandler.SetBaseCookie(http.Cookie{
HttpOnly: true,
Path: "/",
Secure: true,
})
return csrfHandler
}

View File

@ -23,7 +23,7 @@ func (app *application) routes() http.Handler {
fileServer := http.FileServer(http.Dir("./ui/static")) fileServer := http.FileServer(http.Dir("./ui/static"))
router.Handler(http.MethodGet, "/static/*filepath", http.StripPrefix("/static", fileServer)) router.Handler(http.MethodGet, "/static/*filepath", http.StripPrefix("/static", fileServer))
dynamic := alice.New(app.sessionManager.LoadAndSave) dynamic := alice.New(app.sessionManager.LoadAndSave, noSurf)
router.Handler(http.MethodGet, "/", dynamic.ThenFunc(app.home)) router.Handler(http.MethodGet, "/", dynamic.ThenFunc(app.home))
router.Handler(http.MethodGet, "/snippet/view/:id", dynamic.ThenFunc(app.snippetView)) router.Handler(http.MethodGet, "/snippet/view/:id", dynamic.ThenFunc(app.snippetView))

View File

@ -15,6 +15,7 @@ type templateData struct {
Form any Form any
Flash string Flash string
IsAuthenticated bool IsAuthenticated bool
CSRFToken string
} }
// humanDate ... // humanDate ...

View File

@ -9,5 +9,6 @@ require (
github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/justinas/alice v1.2.0 // indirect github.com/justinas/alice v1.2.0 // indirect
github.com/justinas/nosurf v1.1.1 // indirect
golang.org/x/crypto v0.19.0 // indirect golang.org/x/crypto v0.19.0 // indirect
) )

View File

@ -11,5 +11,7 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
github.com/justinas/nosurf v1.1.1 h1:92Aw44hjSK4MxJeMSyDa7jwuI9GR2J/JCQiaKvXXSlk=
github.com/justinas/nosurf v1.1.1/go.mod h1:ALpWdSbuNGy2lZWtyXdjkYv4edL23oSEgfBT1gPJ5BQ=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=

View File

@ -2,6 +2,7 @@
{{define "main"}} {{define "main"}}
<form action='/snippet/create' method='POST'> <form action='/snippet/create' method='POST'>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<div> <div>
<label>Title:</label> <label>Title:</label>
{{with .Form.FieldErrors.title}} {{with .Form.FieldErrors.title}}

View File

@ -1,7 +1,8 @@
{{define "title"}}Login{{end}} {{define "title"}}Login{{end}}
{{define "main"}} {{define "main"}}
<form action='/user/login' method='POST'> <form action='/user/login' method='POST' novalidate>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
{{range .Form.NonFieldErrors}} {{range .Form.NonFieldErrors}}
<div class="error">{{.}}</div> <div class="error">{{.}}</div>
{{end}} {{end}}

View File

@ -1,7 +1,8 @@
{{define "title"}}User Signup{{end}} {{define "title"}}User Signup{{end}}
{{define "main"}} {{define "main"}}
<form action='/user/signup' method='POST'> <form action='/user/signup' method='POST' novalidate>
<input type="hidden" name"csrf_token" value="{{.CSRFToken}}"
<div> <div>
<label>Username:</label> <label>Username:</label>
{{with .Form.FieldErrors.username}} {{with .Form.FieldErrors.username}}

View File

@ -9,6 +9,7 @@
<div> <div>
{{if .IsAuthenticated}} {{if .IsAuthenticated}}
<form action="/user/logout" method="POST"> <form action="/user/logout" method="POST">
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<button>Logout</button> <button>Logout</button>
</form> </form>
{{else}} {{else}}